﻿using HDSmartCommunity.BUS;
using HDSmartCommunity.DAL;
using HDSmartCommunity.HDPlatform;
using HDSmartCommunity.Models;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
using Timer = System.Timers.Timer;

namespace HDSmartCommunity.DevicePlatform
{
    public class HDZHDeviceSerialData
    {

        public static List<string> cmdlist = new List<string>();//发送命令队列
        public int liftid = 0;//设备号
        public List<int> phy_list = new List<int>();//物理楼层列表
        public List<FloorInfo> floor_list = new List<FloorInfo>();//楼层列表
        public static string version_1 = "";
        public static DateTime statussend;//副梯发送状态时间
        public int LogPrint = 0;

        public string devid;//主设备ID
        public string subdevid;//子设备ID
                               // public static MemoryCache memoryCache = new MemoryCache(new MemoryCacheOptions() { });
        public static List<HDZHCurrentElevatorStatus> status_list = new List<HDZHCurrentElevatorStatus>();
        public DevInfo devinfo;
        public static object sendlocker = new object();
        public static object carstatuslocker = new object();
        public LogPrint logPrint;
        public int reporttime = 0;
        System.Timers.Timer reporttimer = null;
        public static CancellationTokenSource report_tokenSource = new CancellationTokenSource();
        public CancellationToken report_token = report_tokenSource.Token;
        public ManualResetEvent report_resetEvent = new ManualResetEvent(true);

        #region 访客器
        public SerialPort myS0SerialPort_1 = new SerialPort();
        public static List<HDCmdInfo> cmd_list = new List<HDCmdInfo>();
        private static object slavesendlocker = new object();
        public static int ele_control = -1;//查询状态中梯控模式的值
        public static int _off = -1;//电源是否开启
        public string StatusCmd = string.Empty;//电梯状态命令
        public bool ismaster = false;//是否主梯
        public string StatuCmd;
        public string oldstatus_1 = string.Empty;//电梯上一次状态


        private void SetS0SerialPortConfig(string portName, int baudRate, int parity, int dataBits, int stopBits)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                portName = $"/dev/{portName}";
            }
            // 串口 参数设置
            myS0SerialPort_1.PortName = portName;
            myS0SerialPort_1.BaudRate = baudRate;
            switch (parity)
            {
                case 0:
                default:
                    myS0SerialPort_1.Parity = Parity.None;
                    break;
                case 1:
                    myS0SerialPort_1.Parity = Parity.Odd;
                    break;
                case 2:
                    myS0SerialPort_1.Parity = Parity.Even;
                    break;
                case 3:
                    myS0SerialPort_1.Parity = Parity.Mark;
                    break;
                case 4:
                    myS0SerialPort_1.Parity = Parity.Space;
                    break;
            }
            myS0SerialPort_1.DataBits = ((4 < dataBits) && (dataBits < 9)) ? dataBits : 8;
            switch (stopBits)
            {
                case 0:
                    myS0SerialPort_1.StopBits = StopBits.None;
                    break;
                case 1:
                default:
                    myS0SerialPort_1.StopBits = StopBits.One;
                    break;
                case 2:
                    myS0SerialPort_1.StopBits = StopBits.OnePointFive;
                    break;
                case 3:
                    myS0SerialPort_1.StopBits = StopBits.Two;
                    break;
            }
            //my485SerialPort_1.ReadTimeout = 200;
            myS0SerialPort_1.RtsEnable = true;
            myS0SerialPort_1.DataReceived += new SerialDataReceivedEventHandler(DataReceived_ttyS0);

            // 串口 接收数据处理定时器 参数设置
            SerialPortRecvTimerS0_1 = new System.Timers.Timer();
            SerialPortRecvTimerS0_1.Interval = 100;
            SerialPortRecvTimerS0_1.AutoReset = false;
            SerialPortRecvTimerS0_1.Elapsed += new ElapsedEventHandler(SPRecvTimer_Tick_ttyS0_1);
        }

        /// <summary>
        /// 打开串口
        /// </summary>
        /// <param name="portName">串口号</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="parity">校验位</param>
        /// <param name="dataBits">数据位</param>
        /// <param name="stopBits">停止位</param>
        public void OpenS0SerialPort(string portName, int baudRate, int parity, int dataBits, int stopBits)
        {
            try
            {
                SetS0SerialPortConfig(portName, baudRate, parity, dataBits, stopBits);
                myS0SerialPort_1.Open();
                LogHelper.Log(portName + "打开成功");

            }
            catch (Exception e)
            {
                LogHelper.Log("ttyS0打开异常" + e.ToString());
            }
        }

        /// <summary>
        /// 串口接收数据 位置
        /// </summary>
        private static int pSerialPortRecv_S0_1 = 0;
        /// <summary>
        /// 串口接收字节 缓存区大小
        /// </summary>
        public byte[] byteSerialPortRecvS0_1 = new byte[byteLength];
        /// <summary>
        /// 串口 接收数据处理定时器
        /// </summary>
        private Timer SerialPortRecvTimerS0_1;
        /// <summary>
        /// 广播 收到的数据 事件
        /// </summary>
        public event EventHandler<SerialPort485_1RecvEventArgs> ReceivedDataEventS0_1;
        /// <summary>
        /// 广播 收到的数据
        /// </summary>

        public class SerialPort485_1RecvEventArgs : EventArgs
        {
            /// <summary>
            /// 广播 收到的串口数据
            /// </summary>
            public readonly byte[] RecvData_485_1 = new byte[byteLength];

            /// <summary>
            /// 收到数据 的 长度
            /// </summary>
            public readonly int RecvDataLength_485_1;

            /// <summary>
            /// 将 收到的数据 转化成 待广播的数据
            /// </summary>
            public SerialPort485_1RecvEventArgs(byte[] recvData, int recvDataLength)
            {
                recvData.CopyTo(RecvData_485_1, 0);
                RecvDataLength_485_1 = recvDataLength;
            }
        }

        /// <summary>
        /// 数据处理定时器
        /// 定时检查缓冲区是否有数据，如果有数据则将数据处理并广播。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SPRecvTimer_Tick_ttyS0_1(object sender, EventArgs e)
        {
            byte[] TemporaryData = new byte[byteLength];
            int TemporaryDataLength = 0;

            if (ReceivedDataEventS0_1 != null)
            {
                byteSerialPortRecvS0_1.CopyTo(TemporaryData, 0);
                TemporaryDataLength = pSerialPortRecv_S0_1;

                ReceivedDataEventS0_1.Invoke(this, new SerialPort485_1RecvEventArgs(TemporaryData, TemporaryDataLength));
                // 数据处理完后，将指针指向数据头，等待接收新的数据
                pSerialPortRecv_S0_1 = 0;
            }
        }

        private void DataReceived_ttyS0(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                SerialPortRecvTimerS0_1.Stop();

                byte[] ReadBuf = new byte[myS0SerialPort_1.BytesToRead];
                if (pSerialPortRecv_S0_1 > byteLength - ReadBuf.Length)
                {
                    pSerialPortRecv_S0_1 = 0;
                }
                myS0SerialPort_1.Read(ReadBuf, 0, ReadBuf.Length);
                ReadBuf.CopyTo(byteSerialPortRecvS0_1, pSerialPortRecv_S0_1);
                pSerialPortRecv_S0_1 += ReadBuf.Length;
                LogHelper.Log("收到访客器数据" + ToHexs(ReadBuf));
                try
                {
                    for (int i = 0; i < byteSerialPortRecvS0_1.Length; i++)
                    {
                        if (byteSerialPortRecvS0_1[i] == liftid && byteSerialPortRecvS0_1[i + 1] == 0x10 && byteSerialPortRecvS0_1[i + 5] == 0x05)
                        {
                            string strCmd = string.Empty;
                            byte[] buffers = new byte[8];
                            if (i + 8 < byteLength - 1)
                            {
                                for (int j = 0; j < 8; j++)
                                {
                                    buffers[j] = byteSerialPortRecvS0_1[i + j];
                                }
                                int length = buffers.Length;
                                byte[] crcdata = new byte[length - 2];
                                for (int k = 0; k < length - 2; k++)
                                {
                                    crcdata[k] = buffers[k];
                                }
                                byte[] crc = Crc18(crcdata);
                                if (crc[0] == buffers[length - 1] && crc[1] == buffers[length - 2])
                                {
                                    Array.Clear(byteSerialPortRecvS0_1, i, buffers.Length);
                                }
                            }
                        }
                        else if (byteSerialPortRecvS0_1[i] == liftid && byteSerialPortRecvS0_1[i + 1] == 0x03 && byteSerialPortRecvS0_1[i + 2] == 8)
                        {
                            string data = string.Empty;
                            string strCmd = string.Empty;
                            int numcount = Convert.ToInt32(byteSerialPortRecvS0_1[i + 2]);
                            byte[] buffers = new byte[numcount + 5];
                            if (i + numcount + 5 < byteLength - 1)
                            {
                                for (int j = 0; j < numcount + 5; j++)
                                {
                                    buffers[j] = byteSerialPortRecvS0_1[i + j];
                                }

                                int length = buffers.Length;
                                byte[] crcdata = new byte[length - 2];
                                for (int k = 0; k < length - 2; k++)
                                {
                                    crcdata[k] = buffers[k];
                                }
                                byte[] crc = Crc18(crcdata);
                                if (crc[0] == buffers[length - 1] && crc[1] == buffers[length - 2])
                                {
                                    Array.Clear(byteSerialPortRecvS0_1, i, buffers.Length);

                                    byte[] status = buffers.Skip(3).Take(8).ToArray();
                                    string newstatus = ToHexs(status);

                                    if (TcpAuthorize)
                                    {
                                        if (ele_control == 0 && face_device_status == 1)
                                        {
                                            LogHelper.Log("人脸设备在线，访客器退出梯控，平台下发梯控，进入梯控");
                                            HDLadderControl(liftid);
                                        }
                                        else if (ele_control == 1 && face_device_status == 0)
                                        {
                                            LogHelper.Log("人脸设备不在线，访客器进入梯控，平台下发梯控，退出梯控");
                                            HDExitControl(liftid);
                                        }
                                    }
                                    else
                                    {
                                        if (ele_control == 1)
                                        {
                                            LogHelper.Log("访客器进入梯控，平台下发梯控，退出梯控");
                                            HDExitControl(liftid);
                                        }
                                    }

                                    if (newstatus != oldstatus_1)//状态与上一次不一致
                                    {
                                        //解析电梯状态数据
                                        LogHelper.Log("电梯状态点：" + newstatus);
                                        HDZHCurrentElevatorStatus elevatorPoint = ParsingData(liftid, buffers);

                                        data += liftid.ToString("X").PadLeft(2, '0');
                                        if (elevatorPoint.Up == 1)
                                        {
                                            data += " 01";
                                        }
                                        else if (elevatorPoint.Down == 1)
                                        {
                                            data += " 02";
                                        }
                                        else if (elevatorPoint.Fault == 1)
                                        {
                                            data += " 80";
                                        }
                                        else if (elevatorPoint.Up == 0 && elevatorPoint.Down == 0)
                                        {
                                            data += " 00";
                                        }

                                        if (elevatorPoint.Open == 1)
                                        {
                                            data += " 10";
                                        }
                                        else if (elevatorPoint.Open == 1)
                                        {
                                            data += " 12";
                                        }
                                        else if (elevatorPoint.Close == 1)
                                        {
                                            data += " 13";
                                        }
                                        else
                                        {
                                            data += " 80";
                                        }

                                        if (elevatorPoint.PhysicalFloor == 0)
                                        {
                                            data += " 00 00";
                                        }
                                        else
                                        {
                                            List<int> show_floor_list = ToActFloorByPhy(elevatorPoint.PhysicalFloor);
                                            string value = string.Empty;
                                            if (show_floor_list[0] > 0)
                                            {
                                                value = "0000000" + Convert.ToString(show_floor_list[0], 2).PadLeft(9, '0');
                                            }
                                            else
                                            {
                                                value = "0000001" + Convert.ToString(Math.Abs(show_floor_list[0]), 2).PadLeft(9, '0');
                                            }
                                            data += " " + string.Format("{0:X}", Convert.ToInt32(value.Substring(0, 8), 2)).PadLeft(2, '0') + " " + string.Format("{0:X}", Convert.ToInt32(value.Substring(8, 8), 2)).PadLeft(2, '0');
                                        }
                                        StatusCmd = data;
                                        //副电梯，通过Tcp发送至主电梯
                                        if (!ismaster)
                                        {
                                            LogHelper.Log("电梯状态变更,发送给主梯");
                                            SlaveCmdSend(StatusCmd);
                                        }

                                        oldstatus_1 = newstatus;
                                    }
                                    else
                                    {
                                        if (!ismaster)//数据状态与上一次相同，1s发送一次
                                        {
                                            LogHelper.Log("数据状态与上一次相同，1s发送一次");
                                            if (SlaveStatusCmd() > 1000)
                                            {
                                                SlaveCmdSend(StatusCmd);
                                            }
                                        }
                                        int index = status_list.FindIndex(x => x.liftid == liftid);
                                        if (index > -1)
                                        {
                                            HDZHCurrentElevatorStatus currentElevator_old = status_list[index];
                                            currentElevator_old.Update = DateTime.Now;
                                            status_list[index] = currentElevator_old;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex1)
                {
                    LogHelper.Log(ex1.ToString());
                }

                SerialPortRecvTimerS0_1.Start();
            }
            catch (Exception)
            {
            }

        }
        //查询副梯发送状态
        public int SlaveStatusCmd()
        {
            int i = 9999;
            if (statussend.Year == 1)
            {
                return i;
            }
            else
            {
                TimeSpan ts1 = new TimeSpan(DateTime.Now.Ticks);
                TimeSpan ts2 = new TimeSpan(statussend.Ticks);
                TimeSpan ts3 = ts1.Subtract(ts2).Duration();
                i = (int)ts3.TotalMilliseconds;
            }

            return i;
        }

        //解析电梯状态
        public HDZHCurrentElevatorStatus ParsingData(int devid, byte[] crcdata)
        {
            HDZHCurrentElevatorStatus currentElevatorStatus = new HDZHCurrentElevatorStatus();
            HDZHCurrentElevatorStatus currentElevator_old = new HDZHCurrentElevatorStatus();
            try
            {
                //电梯物理楼层 40001
                currentElevatorStatus.PhysicalFloor = Convert.ToInt32(crcdata[4].ToString().PadLeft(2, '0'));
                byte[] floorbuffer = new byte[2];
                floorbuffer[0] = crcdata[5];
                floorbuffer[1] = crcdata[6];
                string _showfloor = HexToString(floorbuffer);
                //电梯显示楼层 40002
                if (floorbuffer[0] == 0 && floorbuffer[1] == 0)
                {
                    currentElevatorStatus.DisplayFloor = "0";
                }
                else
                {
                    if (_showfloor.Substring(0, 1) == "0")
                    {
                        currentElevatorStatus.DisplayFloor = _showfloor.Substring(1, 1);
                    }
                    else
                    {
                        currentElevatorStatus.DisplayFloor = _showfloor;
                    }
                }
                //电梯运行点位40003
                string point_run_h = Convert.ToString(crcdata[7], 2).PadLeft(8, '0');
                string point_run_l = Convert.ToString(crcdata[8], 2).PadLeft(8, '0');
                currentElevatorStatus.liftid = liftid;
                currentElevatorStatus.Up = Convert.ToInt32(point_run_l.Substring(7, 1));
                currentElevatorStatus.Down = Convert.ToInt32(point_run_l.Substring(6, 1));
                currentElevatorStatus.Open = Convert.ToInt32(point_run_l.Substring(5, 1));
                currentElevatorStatus.Close = Convert.ToInt32(point_run_l.Substring(4, 1));
                currentElevatorStatus.Fault = Convert.ToInt32(point_run_l.Substring(3, 1));
                currentElevatorStatus.Control = Convert.ToInt32(point_run_l.Substring(2, 1));
                currentElevatorStatus.Update = DateTime.Now;
                string state = JsonConvert.SerializeObject(currentElevatorStatus);
                int index = status_list.FindIndex(x => x.liftid == liftid);
                if (index > -1)
                {
                    currentElevator_old = status_list[index];
                    status_list[index] = currentElevatorStatus;
                }
                else
                {
                    status_list.Add(currentElevatorStatus);
                }
                if (currentElevator_old != null)
                {
                    if (currentElevator_old.Fault != currentElevatorStatus.Fault)
                    {
                        if (currentElevatorStatus.Fault == 1)
                        {
                            LogHelper.Log("电梯故障");
                        }
                        else if (currentElevatorStatus.Fault == 0)
                        {
                            LogHelper.Log("电梯恢复故障");
                        }
                    }
                }
                ele_control = currentElevatorStatus.Control;
                return currentElevatorStatus;
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
                return currentElevatorStatus;
            }
        }

        //发送状态给主梯
        public void SlaveCmdSend(string cmd)
        {
            lock (slavesendlocker)
            {
                SendToServer(cmd);
            }
        }

        //访客器发送命令
        public bool SendMsg(string data)
        {
            try
            {
                myS0SerialPort_1.Write(ToBytesSendDate(data), 0, ToBytesSendDate(data).Length);
                if (data != StatuCmd)
                {
                    LogHelper.Log("发送成功" + data);
                }
                //LogHelper.Log(data);
                //CKSendMsg(data, ttrAMA3_send);
                return true;
            }
            catch (Exception e)
            {

                LogHelper.Log(data + "命令发送失败");
                return false;
            }
        }

        // 访客器查询命令生成
        public void GetCmd(int devid, int add, int count)
        {
            string addhex = (add - 1).ToString("X").PadLeft(4, '0');
            string numhex = count.ToString("X").PadLeft(4, '0');
            string strcmd = devid.ToString("X").PadLeft(2, '0') + " 03 " + addhex.Substring(0, 2) + " " + addhex.Substring(2, 2) + " " + numhex.Substring(0, 2) + " " + numhex.Substring(2, 2);
            byte[] data = ToBytesSendDate(strcmd);
            byte[] crc = Crc18(data);
            strcmd += " " + crc[1].ToString("X").PadLeft(2, '0') + " " + crc[0].ToString("X").PadLeft(2, '0');
            StatuCmd = strcmd;
        }

        //根据物理楼层获取实际楼层信息
        public List<int> ToActFloorByPhy(int phy_floor)
        {
            List<int> list = new List<int>();
            int index = floor_list.FindIndex(x => x.actualfloor == phy_floor);
            if (index > -1)
            {
                list.Add(floor_list[index].actualfloor);
            }
            return list;
        }

        #endregion

        #region 联动控制器
        public SerialPort myS1SerialPort_2 = new SerialPort();
        public string SlaveStatus;//副梯状态命令
        public int SlaveInterval = 0;
        public bool parallel = false;
        public int interval;//访客联动副梯延迟回复时间

        private void SetS1SerialPortConfig_2(string portName, int baudRate, int parity, int dataBits, int stopBits)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                portName = $"/dev/{portName}";
            }
            // 串口 参数设置
            myS1SerialPort_2.PortName = portName;
            myS1SerialPort_2.BaudRate = baudRate;
            switch (parity)
            {
                case 0:
                default:
                    myS1SerialPort_2.Parity = Parity.None;
                    break;
                case 1:
                    myS1SerialPort_2.Parity = Parity.Odd;
                    break;
                case 2:
                    myS1SerialPort_2.Parity = Parity.Even;
                    break;
                case 3:
                    myS1SerialPort_2.Parity = Parity.Mark;
                    break;
                case 4:
                    myS1SerialPort_2.Parity = Parity.Space;
                    break;
            }
            myS1SerialPort_2.DataBits = ((4 < dataBits) && (dataBits < 9)) ? dataBits : 8;
            switch (stopBits)
            {
                case 0:
                    myS1SerialPort_2.StopBits = StopBits.None;
                    break;
                case 1:
                default:
                    myS1SerialPort_2.StopBits = StopBits.One;
                    break;
                case 2:
                    myS1SerialPort_2.StopBits = StopBits.OnePointFive;
                    break;
                case 3:
                    myS1SerialPort_2.StopBits = StopBits.Two;
                    break;
            }
            myS1SerialPort_2.ReadTimeout = -1;
            myS1SerialPort_2.RtsEnable = true;
            myS1SerialPort_2.DataReceived += new SerialDataReceivedEventHandler(DataReceived_ttyS1);

            // 串口 接收数据处理定时器 参数设置
            SerialPortRecvTimerS1_2 = new Timer();
            SerialPortRecvTimerS1_2.Interval = 100;
            SerialPortRecvTimerS1_2.AutoReset = false;
            SerialPortRecvTimerS1_2.Elapsed += new ElapsedEventHandler(SPRecvTimer_Tick_ttyS1_2);
        }

        public void OpenS1SerialPort_2(string portName, int baudRate, int parity, int dataBits, int stopBits)
        {
            try
            {
                SetS1SerialPortConfig_2(portName, baudRate, parity, dataBits, stopBits);
                myS1SerialPort_2.Open();
                LogHelper.Log(portName + "打开成功");
            }
            catch (Exception e)
            {
                LogHelper.Log("ttyS1打开异常" + e.ToString());
            }
        }

        /// <summary>
        /// 串口接收数据 位置
        /// </summary>
        private static int pSerialPortRecv_S1_2 = 0;
        /// <summary>
        /// 串口接收字节 缓存区大小
        /// </summary>
        public byte[] byteSerialPortRecvS1_2 = new byte[byteLength];
        /// <summary>
        /// 串口 接收数据处理定时器
        /// </summary>
        private Timer SerialPortRecvTimerS1_2;
        /// <summary>
        /// 广播 收到的数据 事件
        /// </summary>
        public event EventHandler<SerialPort485_2RecvEventArgs> ReceivedDataEventS1_2;
        /// <summary>
        /// 广播 收到的数据
        /// </summary>
        public class SerialPort485_2RecvEventArgs : EventArgs
        {
            /// <summary>
            /// 广播 收到的串口数据
            /// </summary>
            public readonly byte[] RecvData_485_2 = new byte[byteLength];

            /// <summary>
            /// 收到数据 的 长度
            /// </summary>
            public readonly int RecvDataLength_485_2;

            /// <summary>
            /// 将 收到的数据 转化成 待广播的数据
            /// </summary>
            public SerialPort485_2RecvEventArgs(byte[] recvData, int recvDataLength)
            {
                recvData.CopyTo(RecvData_485_2, 0);
                RecvDataLength_485_2 = recvDataLength;
            }

        }
        /// <summary>
        /// 数据处理定时器
        /// 定时检查缓冲区是否有数据，如果有数据则将数据处理并广播。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private void SPRecvTimer_Tick_ttyS1_2(object sender, EventArgs e)
        {
            byte[] TemporaryData = new byte[byteLength];
            int TemporaryDataLength = 0;

            if (ReceivedDataEventS1_2 != null)
            {
                byteSerialPortRecvS1_2.CopyTo(TemporaryData, 0);
                TemporaryDataLength = pSerialPortRecv_S1_2;

                ReceivedDataEventS1_2.Invoke(this, new SerialPort485_2RecvEventArgs(TemporaryData, TemporaryDataLength));
                // 数据处理完后，将指针指向数据头，等待接收新的数据
                pSerialPortRecv_S1_2 = 0;
            }
        }

        private void DataReceived_ttyS1(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPortRecvTimerS1_2.Stop();

            try
            {

                byte[] ReadBuf = new byte[myS1SerialPort_2.BytesToRead];
                if (pSerialPortRecv_S1_2 > byteLength - ReadBuf.Length)
                {
                    pSerialPortRecv_S1_2 = 0;
                }
                myS1SerialPort_2.Read(ReadBuf, 0, ReadBuf.Length);
                ReadBuf.CopyTo(byteSerialPortRecvS1_2, pSerialPortRecv_S1_2);
                pSerialPortRecv_S1_2 += ReadBuf.Length;

                string send_data = "访客联动收到数据:" + ToHexs(ReadBuf);
                //CKSendMsg(send_data, ttrAMA2_receive);
                SerialDataSaveLogHelper.Log(send_data);
                for (int i = 0; i < byteSerialPortRecvS1_2.Length; i++)
                {
                    if (byteSerialPortRecvS1_2[i] == 0xAA)
                    {
                        string strCmd = string.Empty;
                        int numcount = Convert.ToInt32(byteSerialPortRecvS1_2[i + 1]);
                        byte[] buffers = new byte[numcount + 2];
                        for (int j = 0; j < numcount + 2; j++)
                        {
                            buffers[j] = byteSerialPortRecvS1_2[i + j];
                        }

                        string data = ToHexs(buffers);
                        string crcdata = CheckSum(data.Substring(3, data.Length - 6)).PadLeft(2, '0');
                        if (data.Substring(data.Length - 2, 2) == crcdata)
                        {
                            string frameid = buffers[2].ToString("X").PadLeft(2, '0');
                            string replay = string.Empty;
                            Outcarevents outcarevents = new Outcarevents();
                            if (buffers[3] == 0x01) //访客联动
                            {
                                outcarevents.cmd = "访客联动";
                                outcarevents.ttrAMA1_data = data;
                                if (buffers[4] == 0xEF)
                                {
                                    replay = HDVisitorLinkage(buffers, liftid, frameid, outcarevents);
                                }
                                else if (buffers[4] == liftid)
                                {
                                    replay = HDVisitorLinkage(buffers, liftid, frameid, outcarevents);
                                }
                            }
                            else if (buffers[3] == 0x02) //外呼
                            {
                                outcarevents.cmd = "外呼";
                                outcarevents.ttrAMA1_data = data;
                                if (buffers[4] == 0xEF)
                                {
                                    LogHelper.Log("外呼主梯发送");
                                    replay = HDOutbound(buffers, liftid, frameid, outcarevents);
                                }
                                else if (buffers[4] == liftid)
                                {
                                    replay = HDOutbound(buffers, liftid, frameid, outcarevents);
                                }

                            }
                            else if (buffers[3] == 0x03) //内呼授权
                            {
                                outcarevents.cmd = "内呼授权";
                                outcarevents.ttrAMA1_data = data;
                                replay = HDCallAuthorization(buffers, liftid, frameid, outcarevents);
                            }
                            else if (buffers[3] == 0x04)//内呼点亮
                            {
                                outcarevents.cmd = "内呼点亮";
                                outcarevents.ttrAMA1_data = data;
                                if (buffers[4] == liftid)
                                {
                                    replay = HDInternalCallOn(buffers, liftid, frameid, outcarevents);
                                }
                            }
                            else if (buffers[3] == 0x05)//查询状态
                            {
                                if (ismaster)//如果是主梯
                                {
                                    if (MasterConnect)//从梯连接，则主电梯回复主从状态
                                    {
                                        LogHelper.Log("状态查询主梯发送主从所有状态");
                                        if (!string.IsNullOrEmpty(StatusCmd) && !string.IsNullOrEmpty(SlaveStatus))
                                        {
                                            replay = "0F " + frameid + " 85 01 02 " + StatusCmd + " " + SlaveStatus;
                                        }
                                        else
                                        {
                                            replay = "05 " + frameid + " 85 00 02";
                                        }
                                    }
                                    else//从梯不连接，主电梯回复自己的状态
                                    {
                                        LogHelper.Log("状态查询主梯发送自己状态");
                                        if (!string.IsNullOrEmpty(StatusCmd))
                                        {
                                            replay = "0A " + frameid + " 85 01 01 " + StatusCmd;
                                        }
                                        else
                                        {
                                            replay = "05 " + frameid + " 85 00 01";
                                        }
                                    }
                                }
                                else//从梯
                                {
                                    if (!QuerySlaveStatus())
                                    {
                                        LogHelper.Log("状态查询副梯发送自己状态");
                                        Wait(SlaveInterval);
                                        if (!string.IsNullOrEmpty(StatusCmd))
                                        {
                                            replay = "0A " + frameid + " 85 01 01 " + StatusCmd;
                                        }
                                        else
                                        {
                                            replay = "05 " + frameid + " 85 00 01";
                                        }
                                    }
                                }
                            }

                            if (!string.IsNullOrEmpty(replay))
                            {
                                LogHelper.Log("回复命令" + replay);
                                try
                                {
                                    replay = replay.TrimEnd(' ');
                                    string crc = CheckSum(replay).PadLeft(2, '0');
                                    strCmd = "AA " + replay + " " + crc;
                                    if (parallel && !ismaster)
                                    {
                                        LogHelper.Log("并联梯,从梯未连接，延迟回复");
                                        Wait(SlaveInterval);
                                    }
                                    ttyS1Send(strCmd);
                                }
                                catch (Exception ex)
                                {
                                    LogHelper.Log(ex.ToString());
                                }
                            }
                            Array.Clear(byteSerialPortRecvS1_2, i, buffers.Length);
                        }
                    }
                }

            }
            catch (Exception)
            {
            }
            SerialPortRecvTimerS1_2.Start();
        }

        //查询是否连接主梯
        public bool QuerySlaveStatus()
        {
            return SlaveConnect;
        }


        //访客联动
        public string HDVisitorLinkage(byte[] buffers, int devid, string frameid, Outcarevents outcarevents)
        {
            string replay = "04 " + frameid + " 81 00";
            string result = "";
            try
            {
                int wh_direction = 36;//前门外呼上行36，前门外呼下行41
                List<int> floorarry = new List<int>();
                List<int> listphy = new List<int>();
                List<int> cu_floor = new List<int>();
                string floorbinary = Convert.ToString(buffers[5], 2).PadLeft(8, '0') + Convert.ToString(buffers[6], 2).PadLeft(8, '0');
                bool isground = floorbinary.Substring(7, 1) == "0" ? true : false;
                int cur_floor = Convert.ToInt32(floorbinary.Substring(8, 8), 2);
                if (!isground)
                {
                    cur_floor = cur_floor * -1;
                }
                cu_floor = ToPhyFloorByact(cur_floor);
                if (buffers[5] == 0xFF && buffers[6] == 0xFF)
                {
                    listphy = phy_list;
                }
                else
                {
                    int count = Convert.ToInt32(buffers[7]);
                    string frontfloor = string.Empty;
                    for (int m = 1; m <= count; m++)
                    {
                        string floorvalue = Reverse(Convert.ToString(buffers[8 + m], 2).PadLeft(8, '0'));
                        frontfloor += floorvalue;
                    }

                    //目的楼层
                    listphy = ToPhyFloor(frontfloor);
                    LogHelper.Log("源物理楼层" + cu_floor[0].ToString());
                    LogHelper.Log("目的物理楼层" + listphy[0].ToString());
                }
                //源楼层

                if (cu_floor[0] < listphy[0])//前门外呼上行
                {
                    wh_direction = 36;
                }
                else//前门外呼下行
                {
                    wh_direction = 41;
                }

                string cmd = string.Empty;
                outcarevents.cmdtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                //bool sendresult = Floor(devid, wh_direction, 5, cu_floor, out cmd);
                cmd = GetFloorCmd(devid, wh_direction, 5, cu_floor);
                HDCmdInfo hDCmdInfo = new HDCmdInfo();
                hDCmdInfo.cmd = cmd;
                hDCmdInfo.time = DateTime.Now;
                hDCmdInfo.cmdType = "访客联动外呼";
                cmd_list.Add(hDCmdInfo);

                cmd = GetFloorCmd(devid, 16, 5, listphy);
                HDCmdInfo hDCmdInfo1 = new HDCmdInfo();
                hDCmdInfo1.cmd = cmd;
                hDCmdInfo1.time = DateTime.Now.AddSeconds(30);
                hDCmdInfo1.cmdType = "访客联动内呼授权";
                cmd_list.Add(hDCmdInfo1);

                result = "04 " + frameid + " 81 01";
                outcarevents.ttrAMA3_data = hDCmdInfo.cmd + ";" + hDCmdInfo1.cmd;
                outcarevents.result = "成功";
                InsertOutcar(outcarevents);

                if (!string.IsNullOrEmpty(result))
                {
                    replay = result;
                }
            }
            catch (Exception e)
            {
                outcarevents.ttrAMA3_data = "";
                outcarevents.result = "失败";
                InsertOutcar(outcarevents);
                LogHelper.Log(e.ToString());
            }

            return replay;
        }

        // 根据实际楼层获取物理楼层信息
        public List<int> ToPhyFloorByact(int act_floor)
        {
            List<int> list = new List<int>();

            int index = floor_list.FindIndex(x => x.actualfloor == act_floor);
            if (index > -1)
            {
                list.Add(floor_list[index].physicsfloor);
            }
            return list;
        }

        // 根据字符串获取物理楼层信息
        public List<int> ToPhyFloor(string floor)
        {
            List<int> list = new List<int>();
            char[] myChar = floor.ToCharArray();
            for (int i = 0; i < myChar.Length; i++)
            {
                if (myChar[i].ToString() == "1")
                {
                    int act = 0;
                    if (i < 8)
                    {
                        act = i - 8;
                    }
                    else
                    {
                        act = i - 7;
                    }
                    int index = floor_list.FindIndex(x => x.actualfloor == act);
                    if (index > -1)
                    {
                        list.Add(floor_list[index].physicsfloor);
                    }
                }
            }

            return list;
        }


        // 联动控制-外呼
        public string HDOutbound(byte[] buffers, int devid, string frameid, Outcarevents outcarevents)
        {
            string replay = string.Empty;
            try
            {
                List<int> floorarry = new List<int>();
                if (buffers[5] == 0xFF && buffers[6] == 0xFF)
                {
                    for (int m = 1; m < 81; m++)
                    {
                        floorarry.Add(m);
                    }
                }
                else
                {
                    string floorbinary = Convert.ToString(buffers[5], 2).PadLeft(8, '0') + Convert.ToString(buffers[6], 2).PadLeft(8, '0');
                    bool isground = floorbinary.Substring(7, 1) == "0" ? true : false;
                    int actfloor = Convert.ToInt32(floorbinary.Substring(8, 8), 2);
                    if (!isground)
                    {
                        actfloor = actfloor * -1;
                    }

                    floorarry = ToPhyFloorByact(actfloor);
                    LogHelper.Log("外呼实际楼层" + actfloor + "物理楼层" + floorarry[0].ToString());
                }
                if (floorarry.Count > 0)
                {
                    int startadd = 0;
                    if (buffers[7] == 0x01)//向上
                    {
                        startadd = 36;
                    }
                    else//向下
                    {
                        startadd = 41;
                    }
                    string cmd = string.Empty;
                    outcarevents.cmdtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    HDCmdInfo hDCmdInfo = new HDCmdInfo();
                    cmd = GetFloorCmd(devid, startadd, 5, floorarry);
                    hDCmdInfo.cmd = cmd;
                    hDCmdInfo.time = DateTime.Now;
                    hDCmdInfo.cmdType = "访客联动外呼";
                    cmd_list.Add(hDCmdInfo);
                    outcarevents.ttrAMA3_data = cmd;

                    outcarevents.result = "成功";
                    replay = "04 " + frameid + " 82 01";
                }
                else
                {
                    outcarevents.result = "失败";
                    replay = "04 " + frameid + " 82 00";
                }

                InsertOutcar(outcarevents);
            }
            catch (Exception ex)
            {
                LogHelper.Log("外呼失败");
                outcarevents.result = "失败";
                outcarevents.reason = "命令下发失败";
                replay = "04 " + frameid + " 82 00";
                InsertOutcar(outcarevents);
            }
            return replay;
        }

        // 联动控制-内呼授权
        public string HDCallAuthorization(byte[] buffers, int devid, string frameid, Outcarevents outcarevents)
        {
            string replay = string.Empty;
            try
            {
                int count = Convert.ToInt32(buffers[5]);
                string frontfloor = string.Empty;
                for (int m = 1; m <= count; m++)
                {
                    string floorvalue = Reverse(Convert.ToString(buffers[6 + m], 2).PadLeft(8, '0'));
                    frontfloor = frontfloor + floorvalue;
                }

                List<int> listphy = ToPhyFloor(frontfloor);
                if (listphy.Count > 0)
                {
                    string cmd = string.Empty;
                    HDCmdInfo hDCmdInfo = new HDCmdInfo();
                    cmd = GetFloorCmd(devid, 16, 5, listphy);
                    hDCmdInfo.cmd = cmd;
                    hDCmdInfo.time = DateTime.Now;
                    hDCmdInfo.cmdType = "访客联动内呼";
                    cmd_list.Add(hDCmdInfo);
                    outcarevents.cmdtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    outcarevents.ttrAMA3_data = cmd;

                    LogHelper.Log("内呼授权成功");
                    outcarevents.result = "成功";
                    replay = "04 " + frameid + " 83 01";
                }
                else
                {
                    outcarevents.result = "失败";
                    outcarevents.reason = "未解析到数据";
                    replay = "04 " + frameid + " 83 00";
                }
            }
            catch (Exception e)
            {
                LogHelper.Log("内呼授权失败");
                outcarevents.result = "失败";
                outcarevents.reason = "命令下发失败";
                replay = "04 " + frameid + " 83 00";
            }
            InsertOutcar(outcarevents);
            return replay;
        }

        // 联动控制-内呼点亮
        public string HDInternalCallOn(byte[] buffers, int devid, string frameid, Outcarevents outcarevents)
        {
            string replay;
            try
            {

                int count = Convert.ToInt32(buffers[5]);
                string frontfloor = string.Empty;
                for (int j = 1; j <= count; j++)
                {
                    string floorvalue = Reverse(Convert.ToString(buffers[6 + j], 2).PadLeft(8, '0'));
                    frontfloor += floorvalue;
                }
                List<int> listphy = ToPhyFloor(frontfloor);
                if (listphy.Count > 0)
                {
                    string cmd = string.Empty;
                    outcarevents.cmdtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                    HDCmdInfo hDCmdInfo = new HDCmdInfo();
                    cmd = GetFloorCmd(devid, 26, 5, listphy);
                    hDCmdInfo.cmd = cmd;
                    hDCmdInfo.time = DateTime.Now;
                    hDCmdInfo.cmdType = "访客联动内呼点亮";
                    cmd_list.Add(hDCmdInfo);

                    outcarevents.ttrAMA3_data = cmd;

                    LogHelper.Log("内呼点亮成功");
                    outcarevents.result = "成功";
                    replay = "04 " + frameid + " 84 01";
                }
                else
                {
                    outcarevents.result = "失败";
                    outcarevents.reason = "未解析到楼层";
                    replay = "04 " + frameid + " 84 00";
                }
            }
            catch (Exception ex)
            {
                LogHelper.Log("内呼点亮失败");
                outcarevents.result = "失败";
                outcarevents.reason = "未发送成功";
                replay = "04 " + frameid + " 84 00";
            }
            InsertOutcar(outcarevents);

            return replay;
        }

        //访客联动回复
        public bool ttyS1Send(string strCmd)
        {
            bool result = false;
            try
            {
                myS1SerialPort_2.Write(ToBytesSendDate(strCmd), 0, ToBytesSendDate(strCmd).Length);
                SerialDataSaveLogHelper.Log("访客联动回复" + strCmd);

            }
            catch
            {
                result = false;
            }
            return result;
        }

        public bool Wait(int second)
        {
            try
            {
                DateTime startTime = DateTime.Now;
                while (true)
                {
                    TimeSpan secondSpan = new TimeSpan(DateTime.Now.Ticks - startTime.Ticks);
                    if (secondSpan.TotalMilliseconds > second)
                    {
                        break;
                    }
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        //访客联动记录
        public void InsertOutcar(Outcarevents outcarevents)
        {
            DeviceDAL da = new DeviceDAL();
            da.InsertOutcar(outcarevents);
        }
        // 字符串倒置
        public static string Reverse(string str)
        {
            char[] arr = str.ToCharArray();
            Array.Reverse(arr);
            return new string(arr);
        }

        // 外呼、内呼、权限命令生成
        public string GetFloorCmd(int devid, int add, int count, List<int> floor)
        {
            string cmd = string.Empty;
            try
            {
                string strcmd = string.Empty;
                string strbyte = string.Empty;
                string strbit = string.Empty;
                for (int i = 1; i < 81; i++)
                {
                    var res1 = floor.Any(e => e == i);
                    if (!res1)
                    {
                        strbit = strbit + "0";
                    }
                    else
                    {
                        strbit = strbit + "1";
                    }
                }
                strbit = Reverse(strbit);

                strcmd = Convert.ToInt32(strbit.Substring(64, 8), 2).ToString("X").PadLeft(2, '0') + " " + Convert.ToInt32(strbit.Substring(72, 8), 2).ToString("X").PadLeft(2, '0') + " " +
                       Convert.ToInt32(strbit.Substring(48, 8), 2).ToString("X").PadLeft(2, '0') + " " + Convert.ToInt32(strbit.Substring(56, 8), 2).ToString("X").PadLeft(2, '0') + " " +
                      Convert.ToInt32(strbit.Substring(32, 8), 2).ToString("X").PadLeft(2, '0') + " " + Convert.ToInt32(strbit.Substring(40, 8), 2).ToString("X").PadLeft(2, '0') + " " +
                      Convert.ToInt32(strbit.Substring(16, 8), 2).ToString("X").PadLeft(2, '0') + " " + Convert.ToInt32(strbit.Substring(24, 8), 2).ToString("X").PadLeft(2, '0') + " " +
                      Convert.ToInt32(strbit.Substring(0, 8), 2).ToString("X").PadLeft(2, '0') + " " + Convert.ToInt32(strbit.Substring(8, 8), 2).ToString("X").PadLeft(2, '0');

                string addhex = (add - 1).ToString("X").PadLeft(4, '0');
                string numhex = count.ToString("X").PadLeft(4, '0');
                string bytecount = (2 * count).ToString("X").PadLeft(2, '0');
                strcmd = liftid.ToString().PadLeft(2, '0') + " 10 " + addhex.Substring(0, 2) + " " + addhex.Substring(2, 2) + " " + numhex.Substring(0, 2) + " " + numhex.Substring(2, 2) + " " + bytecount + " " + strcmd;

                byte[] data = ToBytesSendDate(strcmd);
                byte[] crc = Crc18(data);
                strcmd += " " + crc[1].ToString("X").PadLeft(2, '0') + " " + crc[0].ToString("X").PadLeft(2, '0');
                cmd = strcmd;
            }
            catch (Exception ex)
            {
                LogHelper.Log("命令解析异常");
            }
            return cmd;
        }
        #endregion

        #region 人脸识别面板
        public SerialPort mySerialPort_Face = new SerialPort();
        public DateTime sendtime = DateTime.Now;//七合一面板心跳最新接收时间
        public static int face_device_status = 0;//人脸设备状态，0=设备断开，1=设备连接
        public int sign_kt = -1;

        /// <summary>
        /// 设置 串口配置
        /// </summary>
        /// <param name="portName">串口号</param>
        /// <param name="baudRate">波特率</param>
        /// <param name="parity">校验位</param>
        /// <param name="dataBits">数据位</param>
        /// <param name="stopBits">停止位</param>

        private void SetFaceSerialPortConfig(string portName, int baudRate, int parity, int dataBits, int stopBits)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                portName = $"/dev/{portName}";
            }
            // 串口 参数设置
            mySerialPort_Face.PortName = portName;
            mySerialPort_Face.BaudRate = baudRate;
            switch (parity)
            {
                case 0:
                default:
                    mySerialPort_Face.Parity = Parity.None;
                    break;
                case 1:
                    mySerialPort_Face.Parity = Parity.Odd;
                    break;
                case 2:
                    mySerialPort_Face.Parity = Parity.Even;
                    break;
                case 3:
                    mySerialPort_Face.Parity = Parity.Mark;
                    break;
                case 4:
                    mySerialPort_Face.Parity = Parity.Space;
                    break;
            }
            mySerialPort_Face.DataBits = ((4 < dataBits) && (dataBits < 9)) ? dataBits : 8;
            switch (stopBits)
            {
                case 0:
                    mySerialPort_Face.StopBits = StopBits.None;
                    break;
                case 1:
                default:
                    mySerialPort_Face.StopBits = StopBits.One;
                    break;
                case 2:
                    mySerialPort_Face.StopBits = StopBits.OnePointFive;
                    break;
                case 3:
                    mySerialPort_Face.StopBits = StopBits.Two;
                    break;
            }
            mySerialPort_Face.ReadTimeout = -1;
            mySerialPort_Face.RtsEnable = true;
            mySerialPort_Face.DataReceived += new SerialDataReceivedEventHandler(DataReceived_ttyFace);

            // 串口 接收数据处理定时器 参数设置
            SerialPortRecvTimerFace = new Timer();
            SerialPortRecvTimerFace.Interval = 100;
            SerialPortRecvTimerFace.AutoReset = false;
            SerialPortRecvTimerFace.Elapsed += new ElapsedEventHandler(SPRecvTimer_Tick_ttyFace);
        }

        public void OpenFaceSerialPort(string portName, int baudRate, int parity, int dataBits, int stopBits)
        {
            try
            {
                SetFaceSerialPortConfig(portName, baudRate, parity, dataBits, stopBits);
                mySerialPort_Face.Open();
                LogHelper.Log(portName + "打开成功");
            }
            catch (Exception e)
            {
                LogHelper.Log("ttyUSB0打开异常" + e.ToString());
            }
        }
        /// <summary>
        /// 串口接收数据 位置
        /// </summary>
        private static int pSerialPortRecv_Face = 0;
        /// <summary>
        /// 缓存区大小的长度    
        /// 缓冲区可调大
        /// （接收数据处理定时器 内接收数据量 小于下面设置的值即可）
        /// </summary>
        private static int byteLength = 40960;
        /// <summary>
        /// 串口接收字节 缓存区大小
        /// </summary>
        public byte[] byteSerialPortRecvFace = new byte[byteLength];
        /// <summary>
        /// 串口 接收数据处理定时器
        /// </summary>
        private Timer SerialPortRecvTimerFace;
        /// <summary>
        /// 广播 收到的数据 事件
        /// </summary>
        public event EventHandler<SerialPortFaceRecvEventArgs> ReceivedDataEventFace;
        /// <summary>
        /// 广播 收到的数据
        /// </summary>
        public class SerialPortFaceRecvEventArgs : EventArgs
        {
            /// <summary>
            /// 广播 收到的串口数据
            /// </summary>
            public readonly byte[] RecvData_Face = new byte[byteLength];

            /// <summary>
            /// 收到数据 的 长度
            /// </summary>
            public readonly int RecvDataLength_Face;

            /// <summary>
            /// 将 收到的数据 转化成 待广播的数据
            /// </summary>
            public SerialPortFaceRecvEventArgs(byte[] recvData, int recvDataLength)
            {
                recvData.CopyTo(RecvData_Face, 0);
                RecvDataLength_Face = recvDataLength;
            }
        }

        /// <summary>
        /// 数据处理定时器
        /// 定时检查缓冲区是否有数据，如果有数据则将数据处理并广播。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>

        private void SPRecvTimer_Tick_ttyFace(object sender, EventArgs e)
        {
            byte[] TemporaryData = new byte[byteLength];
            int TemporaryDataLength = 0;

            if (ReceivedDataEventFace != null)
            {
                byteSerialPortRecvFace.CopyTo(TemporaryData, 0);
                TemporaryDataLength = pSerialPortRecv_Face;

                ReceivedDataEventFace.Invoke(this, new SerialPortFaceRecvEventArgs(TemporaryData, TemporaryDataLength));
                // 数据处理完后，将指针指向数据头，等待接收新的数据
                pSerialPortRecv_Face = 0;
            }
        }
        private void DataReceived_ttyFace(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPortRecvTimerFace.Stop();
            try
            {
                byte[] ReadBuf = new byte[mySerialPort_Face.BytesToRead];
                if (pSerialPortRecv_Face > byteLength - ReadBuf.Length)
                {
                    pSerialPortRecv_Face = 0;
                }
                mySerialPort_Face.Read(ReadBuf, 0, ReadBuf.Length);
                ReadBuf.CopyTo(byteSerialPortRecvFace, pSerialPortRecv_Face);
                pSerialPortRecv_Face += ReadBuf.Length;
                //SerialDataSaveLogHelper.Log("收到人脸设备信息" + ToHexs(ReadBuf));
                bool result;
                try
                {
                    for (int i = 0; i < byteSerialPortRecvFace.Length; i++)
                    {
                        if (byteSerialPortRecvFace[i] == 0xAA)
                        {
                            string strCmd = string.Empty;
                            int numcount = Convert.ToInt32(byteSerialPortRecvFace[i + 1]);
                            byte[] buffers = new byte[numcount + 2];
                            for (int j = 0; j < numcount + 2; j++)
                            {
                                buffers[j] = byteSerialPortRecvFace[i + j];
                            }
                            string data1 = ToHexs(buffers);
                            string crcdata = CheckSum(data1.Substring(3, data1.Length - 6)).PadLeft(2, '0');
                            if (data1.Substring(data1.Length - 2, 2) == crcdata)
                            {
                                Array.Clear(byteSerialPortRecvFace, i, buffers.Length);

                                string replay = string.Empty;
                                if (buffers[3] == 0x11)
                                {
                                    int credencetype = buffers[38];
                                    string uuid = string.Empty;
                                    for (int k = 0; k < 32; k++)
                                    {
                                        uuid += char.ConvertFromUtf32(buffers[5 + k]);
                                    }
                                    string subdevice = subdevid;
                                    LogHelper.Log("人脸设备id" + subdevice);
                                    VoucherInfo voucherInfo = GetVoucherInfo(uuid, subdevice);
                                    Incarevents incarevents = new Incarevents();
                                    List<int> floorlist = new List<int>();
                                    if (voucherInfo == null)
                                    {
                                        LogHelper.Log(string.Format("UUID为{0}未找到凭证信息", uuid));
                                        replay = "04 " + buffers[2].ToString("X").PadLeft(2, '0') + " 91 02";
                                    }
                                    else
                                    {
                                        incarevents.credenctype = credencetype;
                                        incarevents.ttrAMA2_data = data1;
                                        incarevents.UUID = voucherInfo.UUID;
                                        //incarevents.credenctype = voucherInfo.CredenceType;
                                        if (!string.IsNullOrEmpty(voucherInfo.StartTime) && !string.IsNullOrEmpty(voucherInfo.OverTime))
                                        {
                                            DateTime dt1 = Convert.ToDateTime(voucherInfo.StartTime);
                                            DateTime dt2 = Convert.ToDateTime(voucherInfo.OverTime);
                                            if (DateTime.Compare(DateTime.Now, dt1) > 0 && DateTime.Compare(dt2, DateTime.Now) > 0)
                                            {
                                                var list = voucherInfo.elevatorAuthFloor.Split(',').ToList();
                                                string cmd = string.Empty;
                                                foreach (var item in list)
                                                {
                                                    floorlist.Add(GetPhyFloorByDisplay(item)[0]);
                                                }
                                                if (floorlist.Count > 1)
                                                {
                                                    //多楼层授权
                                                    cmd = GetFloorCmd(1, 16, 5, floorlist);
                                                    HDCmdInfo hDCmdInfo = new HDCmdInfo();
                                                    hDCmdInfo.cmd = cmd;
                                                    hDCmdInfo.time = DateTime.Now;
                                                    hDCmdInfo.cmdType = "人脸识别多层授权";
                                                    cmd_list.Add(hDCmdInfo);
                                                    incarevents.operatetype = 2;
                                                }
                                                else
                                                {
                                                    //单楼层点亮
                                                    cmd = GetFloorCmd(1, 26, 5, floorlist);
                                                    HDCmdInfo hDCmdInfo = new HDCmdInfo();
                                                    hDCmdInfo.cmd = cmd;
                                                    hDCmdInfo.time = DateTime.Now;
                                                    hDCmdInfo.cmdType = "人脸识别单层点亮";
                                                    cmd_list.Add(hDCmdInfo);
                                                    incarevents.operatetype = 1;
                                                }

                                                incarevents.cmdtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                                incarevents.ttrAMA3_data = cmd;
                                                incarevents.result = "success";
                                                replay = "04 " + buffers[2].ToString("X").PadLeft(2, '0') + " 91 01";

                                                InsertIncar(incarevents);
                                            }
                                            else
                                            {
                                                replay = "04 " + buffers[2].ToString("X").PadLeft(2, '0') + " 91 07";
                                            }
                                        }
                                        else
                                        {
                                            replay = "04 " + buffers[2].ToString("X").PadLeft(2, '0') + " 91 07";
                                        }
                                    }
                                }
                                else if (buffers[3] == 0x12)
                                {
                                    replay = "05 " + buffers[2].ToString("X").PadLeft(2, '0') + " 92 01 00";
                                    LogHelper.Log("恒大下发模式" + TcpAuthorize.ToString());

                                    byte[] basic_data = new byte[2];
                                    basic_data[0] = buffers[27];
                                    basic_data[1] = buffers[26];
                                    BitArray bits;
                                    bits = new BitArray(basic_data);
                                    bool mb_status = bits.Get(6);
                                    if (!mb_status)
                                    {
                                        sendtime = DateTime.Now;
                                        face_device_status = 1;
                                        if (TcpAuthorize)//恒大进入梯控
                                        {
                                            if (ele_control == 0)//普通模式下,收到心跳后，由普通变为授权
                                            {
                                                HDLadderControl(liftid);
                                                ModeRecord mode = new ModeRecord();
                                                mode.workmode = 0;
                                                mode.updatetime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                                mode.reason = "重新收到心跳，切换为授权模式";
                                                InsertModeRecord(mode);
                                            }
                                        }
                                    }
                                    else
                                    {
                                        face_device_status = 0;
                                        LogHelper.Log("人脸信息故障");
                                        if (TcpAuthorize)//恒大进入梯控
                                        {
                                            LogHelper.Log("恒大进入梯控，当前设备状态" + Elevatormode);
                                            if (ele_control == 1)//故障，由授权改为普通
                                            {
                                                HDExitControl(liftid);
                                                sign_kt = -1;
                                                ModeRecord mode = new ModeRecord();
                                                mode.workmode = 1;
                                                mode.updatetime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                                mode.reason = "收到故障信号，切换为普通模式";
                                                InsertModeRecord(mode);
                                            }
                                        }
                                    }
                                }

                                if (!string.IsNullOrEmpty(replay))
                                {
                                    try
                                    {
                                        string crc = CheckSum(replay).PadLeft(2, '0');
                                        strCmd = "AA " + replay + " " + crc;
                                        mySerialPort_Face.Write(ToBytesSendDate(strCmd), 0, ToBytesSendDate(strCmd).Length);
                                        //SerialDataSaveLogHelper.Log("回复人脸设备信息" + strCmd);
                                    }
                                    catch (Exception ex)
                                    {
                                        LogHelper.Log("人脸回复异常" + ex.ToString());
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception ex1)
                {
                }

            }
            catch (Exception)
            {
            }
            SerialPortRecvTimerFace.Start();
        }

        //根据显示楼层获取物理楼层
        public List<int> GetPhyFloorByDisplay(string displayfloor)
        {
            List<int> list = new List<int>();
            int index = floor_list.FindIndex(x => x.displayfloor == displayfloor);
            if (index > -1)
            {
                list.Add(floor_list[index].physicsfloor);
            }
            return list;
        }

        //轿厢内刷卡 人脸识别记录
        public void InsertIncar(Incarevents incarevents)
        {
            DeviceDAL da = new DeviceDAL();
            da.InsertIncar(incarevents);
        }
        //梯控模式切换记录
        public void InsertModeRecord(ModeRecord modeRecord)
        {
            DeviceDAL da = new DeviceDAL();
            da.InsertModeRecord(modeRecord);
        }
        // 根据uuid或者卡号获取凭证信息
        public VoucherInfo GetVoucherInfo(string voucher, string subdeviceid)
        {
            string strSql = "SELECT * FROM cardinfo WHERE UUID='" + voucher + "' LIMIT 0,1";

            CommFN<VoucherInfo> fn = new CommFN<VoucherInfo>();
            return fn.GetData(strSql);
        }

        public void IncidentReporting(VoucherInfo info)
        {
            Incident incident = new Incident();
            incident.UUID = info.UUID;
            incident.credenceNo = info.cardID;
            incident.RecordType = GetRecordType(info.CredenceType);
            incident.CredenceType = Convert.ToInt32(info.CredenceType);
            string[] strArray = info.elevatorAuthFloor.Split(new char[] { ',' });
            incident.DestFloor = Array.ConvertAll<string, int>(strArray, s => int.Parse(s));
            incident.opTime = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
            IncidentReporting(incident);
        }

        /// <summary>
        /// 乘梯事件上报
        /// </summary>
        public void IncidentReporting(Incident incident)
        {
            try
            {
                incident.deviceID = subdevid;
                IncidentMessage replay = new IncidentMessage();
                List<Incident> list = new List<Incident>();
                list.Add(incident);
                replay.Command = "FAC_ELEVATOR_RECORD";
                replay.Data = list;
                string str = JsonConvert.SerializeObject(replay);
                string zs = IntToHex(count).PadLeft(8, '0'); ;
                string datazs = zs.Substring(0, 2) + " " + zs.Substring(2, 2) + " " + zs.Substring(4, 2) + " " + zs.Substring(6, 2);
                string strCmd = StringToHex(str);
                int num = strCmd.Split(' ').Length;
                string datalength = IntToHex(num).PadLeft(8, '0');
                string length = datalength.Substring(0, 2) + " " + datalength.Substring(2, 2) + " " + datalength.Substring(4, 2) + " " + datalength.Substring(6, 2);
                string crc = CRCCalc(strCmd);
                strCmd = "48 44 58 4D " + StringToHex(devid) + " " + StringToHex("00000000000000000000") + " 00 " + datazs + " " + length + " 00 00 " + crc + " " + strCmd;

                SendToServerMsg(strCmd);
            }
            catch
            {

            }
        }

        public int GetRecordType(int type)
        {
            int RecordType;
            switch (type)
            {
                case 7:
                    RecordType = 30000;
                    break;
                case 6:
                    RecordType = 30004;
                    break;
                case 2:
                    RecordType = 30002;
                    break;
                case 10:
                    RecordType = 30005;
                    break;
                case 8:
                    RecordType = 30003;
                    break;
                case 9:
                    RecordType = 30001;
                    break;
                default:
                    RecordType = 0;
                    break;
            }
            return RecordType;
        }
        #endregion

        #region 公用方法
        //byte转十六进制
        public string ToHexs(byte[] data)
        {
            if (data.Length <= 0) return "";
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sb.Append(data[i].ToString("X2"));
                sb.Append(" ");
            }
            string str = sb.ToString();
            return str.Substring(0, str.Length - 1);
        }

        // CRC校验
        public byte[] Crc18(byte[] buffer, int start = 0, int len = 0)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            ushort crc = 0xFFFF;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (ushort)((crc >> 1) ^ 0xA001);// 0xA001 = reverse 0x8005
                    else
                        crc = (ushort)(crc >> 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc);
            Array.Reverse(ret);
            return ret;
        }

        // 字符串转byte

        public byte[] ToBytesSendDate(string str)
        {
            List<byte> result = new List<byte>();
            if (str.Contains(" "))
            {
                string[] strs = str.Trim().Split(' ');
                foreach (string s in strs)
                {
                    result.Add(Convert.ToByte(s.Trim(), 16));
                }
            }
            else
            {
                result.Add(Convert.ToByte(str, 16));
            }
            return result.ToArray();
        }

        //和校验
        public string CheckSum(string data)
        {
            int sum = data.Split(' ').Select(i => Convert.ToInt32(i, 16)).Sum();
            int mod = sum % 256;
            int crc = 0xFF - mod + 1;
            if (crc == 256)
            {
                return "00";
            }
            return crc.ToString("X");
        }

        //退出梯控
        public bool HDExitControl(int devid)
        {
            try
            {
                string cmd = SinglePointCmd(devid, 57, 1, 0);
                HDCmdInfo hDCmdInfo = new HDCmdInfo();
                hDCmdInfo.cmd = cmd;
                hDCmdInfo.time = DateTime.Now;
                hDCmdInfo.cmdType = "退出梯控";
                cmd_list.Add(hDCmdInfo);
                //cmdlist.Add(cmd);
                return true;
            }
            catch
            {
                return false;
            }
        }

        //进入梯控
        public bool HDLadderControl(int devid)
        {
            try
            {
                string cmd = SinglePointCmd(devid, 57, 1, 1);
                HDCmdInfo hDCmdInfo = new HDCmdInfo();
                hDCmdInfo.cmd = cmd;
                hDCmdInfo.time = DateTime.Now;
                hDCmdInfo.cmdType = "进入梯控";
                cmd_list.Add(hDCmdInfo);
                //cmdlist.Add(cmd);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public string SinglePointCmd(int devid, int add, int count, int value)
        {
            try
            {
                string addhex = (add - 1).ToString("X").PadLeft(4, '0');
                string numhex = count.ToString("X").PadLeft(4, '0');
                string bytenum = (2 * count).ToString("X").PadLeft(2, '0');
                string cmd = "0000000" + value.ToString();
                LogHelper.Log(cmd);
                string strvalue = string.Format("{0:X}", Convert.ToInt32(cmd.Substring(0, 8), 2)).PadLeft(2, '0');
                string strcmd = devid.ToString("X").PadLeft(2, '0') + " 10 " + addhex.Substring(0, 2) + " " + addhex.Substring(2, 2) + " " + numhex.Substring(0, 2) + " " + numhex.Substring(2, 2) + " " + bytenum + " 00" + " " + strvalue;
                byte[] data = ToBytesSendDate(strcmd);
                byte[] crc = Crc18(data);
                strcmd += " " + crc[1].ToString("X").PadLeft(2, '0') + " " + crc[0].ToString("X").PadLeft(2, '0');
                LogHelper.Log("命令" + strcmd);
                return strcmd;
            }
            catch
            {
                return "";
            }
        }

        // 十六进制转string
        public string HexToString(byte[] buffer)
        {
            // 将 byte数组 解码成 字符串：
            string getData = Encoding.Default.GetString(buffer);
            return getData;
        }

        //字符串转十六进制
        public string StringToHex(string strEncode)
        {
            string strReturn = "";
            foreach (short shortx in strEncode.ToCharArray())
            {
                strReturn += shortx.ToString("X2") + " ";
            }
            strReturn = strReturn.TrimEnd(' ').ToUpper();
            return strReturn;
        }

        //int转十六进制
        public string IntToHex(int num)
        {
            string result = "";
            result = Convert.ToString(num, 16).ToUpper();
            return result;
        }

        //查询配置
        public DevInfo GetDevInfo()
        {
            string strSql = "SELECT * FROM devinfo";
            CommFN<DevInfo> fn = new CommFN<DevInfo>();
            return fn.GetData(strSql);
        }

        //CRC校验
        public string CRCCalc(string data)
        {
            string[] datas = data.Split(' ');
            List<byte> bytedata = new List<byte>();

            foreach (string str in datas)
            {
                bytedata.Add(byte.Parse(str, System.Globalization.NumberStyles.AllowHexSpecifier));
            }
            byte[] crcbuf = bytedata.ToArray();
            //计算并填写CRC校验码
            int crc = 0xffff;
            int len = crcbuf.Length;

            for (int j = 0; j < len; j++)
            {
                crc = ((crc >> 8) | (crc << 8)) & 0xffff;
                crc ^= (crcbuf[j] & 0xff);
                crc ^= ((crc & 0xff) >> 4);
                crc ^= (crc << 12) & 0xffff;
                crc ^= ((crc & 0xff) << 5) & 0xffff;
            }
            crc = crc & 0xffff;

            string[] redata = new string[2];
            redata[1] = Convert.ToString((byte)((crc >> 8) & 0xff), 16);
            redata[0] = Convert.ToString((byte)((crc & 0xff)), 16);
            string a = redata[1].ToString().PadLeft(2, '0') + " " + redata[0].ToString().PadLeft(2, '0');
            return a.ToUpper();
        }

        //参数初始化
        public static int Elevatormode = -1;//电梯工作模式,0梯控，1普通
        public static bool TcpAuthorize = false;//恒大平台是否下发进入梯控
        public int packet;//包号
        public int ttrAMA1_receive = 0;
        public int ttrAMA2_receive = 0;
        public int authmode = -1;
        public int light = -1;
        public void ConfigInit()
        {
            try
            {
                JsonConfigHelper jsonConfigHelper = new JsonConfigHelper("appsettings.json");
                DevInfo dev = GetDevInfo();
                if (dev != null)
                {
                    Elevatormode = dev.workmode;
                    ttrAMA1_receive = dev.ttrAMA1_receive;
                    ttrAMA2_receive = dev.ttrAMA2_receive;
                    devinfo = dev;
                    reporttime = dev.intervalTime;
                    liftid = dev.liftid;
                    packet = dev.packet;
                    light = dev.lightmode;
                    authmode = dev.authmode;
                    GetCmd(dev.liftid, 1, 4);
                }
                interval = Convert.ToInt32(jsonConfigHelper["Interval"]);
                SlaveInterval = Convert.ToInt32(jsonConfigHelper["SlaveInterval"]);
                LogPrint = Convert.ToInt32(jsonConfigHelper["LogPrint"]);
                if (Elevatormode == 0)
                {
                    TcpAuthorize = false;
                }
                else if (Elevatormode == 1)
                {
                    TcpAuthorize = true;
                }
            }
            catch (Exception ex)
            {
                LogHelper.Log("参数初始化异常" + ex.ToString());
            }
        }

        //查询所有楼层信息
        public List<FloorInfo> GetAllFloor()
        {
            string strSql = "SELECT * FROM floor ORDER by actualfloor ASC";
            CommFN<FloorInfo> fn = new CommFN<FloorInfo>();
            return fn.GetDataList(strSql);
        }
        #endregion



        #region 检查七合一面板连接状态
        public void CheckDevConnect()
        {
            Task task = new Task(async () =>
            {
                while (true)
                {
                    //CheckRS485Status(liftid);
                    await Task.Delay(5000);
                }
            });
            task.Start();
        }

        public void CheckRS485Status(int devid)
        {
            DateTime now = DateTime.Now;
            TimeSpan ts = now.Subtract(sendtime);
            int sec = (int)ts.TotalSeconds;
            if (TcpAuthorize)//平台下发模式为进入梯控，需要判断心跳
            {
                if (sendtime.Year != 1)
                {
                    if (sec > 180 && face_device_status == 1) //授权模式下，超过180秒未收到心跳
                    {
                        LogHelper.Log("超过3分钟未收到心跳，切换为普通模式");
                        bool result = HDExitControl(devid);
                        if (result)
                        {
                            face_device_status = 0;
                            sign_kt = -1;
                            ModeRecord mode = new ModeRecord();
                            mode.workmode = 1;
                            mode.updatetime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                            mode.reason = "超过3分钟未收到心跳，切换为普通模式";
                            InsertModeRecord(mode);

                            Equipment equipment = new Equipment();
                            equipment.devtype = "七合一面板";
                            equipment.state = 1;
                            equipment.actiontime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                            equipment.reason = "超过3分钟未收到心跳";
                            InsertEquipment(equipment);
                        }
                    }
                    else if (Elevatormode == 0 && sec <= 180)//授权模式下，收到心跳
                    {
                        Equipment equipment = new Equipment();
                        equipment.devtype = "七合一面板";
                        equipment.state = 0;
                        equipment.actiontime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                        equipment.reason = "收到心跳";
                        InsertEquipment(equipment);
                    }
                }
            }
        }
        //新增人脸识别面板在线离线记录
        public void InsertEquipment(Equipment equipment)
        {
            DeviceDAL da = new DeviceDAL();
            da.InsertEquipment(equipment);
        }
        #endregion

        #region 访客器定时发送命令
        public void CheckHDElevatorStatus()
        {
            Task task = new Task(async () =>
            {
                while (true)
                {
                    try
                    {
                        if (cmd_list.Count == 0)
                        {
                            SendMsg(StatuCmd);
                        }
                        else
                        {
                            cmd_list.OrderBy(x => x.time);
                            HDCmdInfo hDCmdInf = cmd_list[0];
                            if (DateTime.Now >= hDCmdInf.time)
                            {
                                if (SendMsg(hDCmdInf.cmd))
                                {
                                    cmd_list.Remove(hDCmdInf);
                                }
                            }
                        }
                    }
                    catch
                    {

                    }
                    await Task.Delay(200);

                }
            });
            task.Start();
        }
        #endregion

        #region 接口方法
        public int power()
        {
            return _off;
        }

        public int TK()
        {
            return ele_control;
        }
        public int GetHdTK()
        {
            DevInfo dev = GetDevInfo();
            int mode;
            if (dev.workmode == 1)
            {
                mode = 0;
            }
            else
            {
                mode = 1;
            }
            return mode;
        }

        public string getversion()
        {
            return version_1;
        }

        //查询主副梯连接状态
        public int GetConnectStaus(int ismaster)
        {
            if (ismaster == 1)
            {
                if (MasterConnect)
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
            else
            {
                if (QuerySlaveStatus())
                {
                    return 1;
                }
                else
                {
                    return 0;
                }
            }
        }
        #endregion

        #region 恒大平台
        public static bool hdpt_connect_flag = false;//恒大平台连接
        public static bool hdpt_reg_flag = false;//恒大平台注册
        public static bool hdpt_heart_flag = false;//恒大心跳
        public static DateTime hdpt_heart_time = DateTime.Now;//恒大发送心跳时间
        public static int hdstatus = 0;//恒大平台连接状态，1：注册中，2：心跳发送中
        public Socket server;//恒大TCP
        public Thread hd_thread;
        public int count = 1;//流水号
        public static ParameterRead Parameter = new ParameterRead();


        //连接恒大平台
        public bool ConnectServer(string serverIP, int port)
        {
            try
            {
                server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                server.Connect(serverIP, port);
                //server.ReceiveTimeout = 10000;
                hd_thread = new Thread(StartReceive);
                hd_thread.Start(server);
                return true;
            }
            catch (Exception e)
            {
                LogHelper.Log("连接恒大异常" + e.ToString());
                return false;
            }
        }

        //接收恒大平台消息
        public void StartReceive(object obj)
        {
            byte[] buffer = new byte[2048];
            int length = 0;
            while (true)
            {
                try
                {
                    length = server.Receive(buffer);
                    if (length == 0)
                    {
                        break;
                    }
                    else
                    {
                        DataSaveLogHelper.Log(ToHexs(buffer.Skip(0).Take(length).ToArray()));
                        if (buffer[0] == 0x48 && buffer[1] == 0x44 && buffer[2] == 0x58 && buffer[3] == 0x4D)
                        {
                            List<byte> data = new List<byte>();

                            string strvalue = buffer[49].ToString("X").PadLeft(2, '0') + buffer[50].ToString("X").PadLeft(2, '0') + buffer[51].ToString("X").PadLeft(2, '0') + buffer[52].ToString("X").PadLeft(2, '0');
                            int value = int.Parse(strvalue, System.Globalization.NumberStyles.HexNumber) + 57;
                            string pack_hex = buffer[45].ToString("X2").PadLeft(2, '0') + buffer[46].ToString("X2").PadLeft(2, '0') + buffer[47].ToString("X2").PadLeft(2, '0') + buffer[48].ToString("X2").PadLeft(2, '0');
                            int packnum = Convert.ToInt32(pack_hex, 16);
                            for (int j = 0; j < length; j++)
                            {
                                if (j < value)
                                {
                                    data.Add(buffer[j]);
                                }
                            }
                            try
                            {
                                ReceiveData message = AnalysisType(data);
                                if (message != null)
                                {
                                    //下发凭证
                                    if (message.Command.ToUpper() == "COM_LOAD_CERTIFICATE")
                                    {
                                        CardInfo card = GetVoucherInfo(message.Data[0].ToString());
                                        if (card != null)
                                        {
                                            bool result = false;
                                            VoucherInfo voucher = QueryVoucher(card);
                                            if (voucher == null)
                                            {
                                                result = InsertVoucher(card);
                                            }
                                            else
                                            {
                                                result = UpdateVoucher(card);
                                            }

                                            Message replay = new Message();
                                            replay.Command = "COM_LOAD_CERTIFICATE";
                                            if (result)
                                            {
                                                replay.Result = 0;
                                            }
                                            else
                                            {
                                                replay.Result = 1;
                                            }
                                            string str = JsonConvert.SerializeObject(replay);
                                            string datazs = string.Format("{0} {1} {2} {3}", data[45].ToString("X").PadLeft(2, '0'), data[46].ToString("X").PadLeft(2, '0'), data[47].ToString("X").PadLeft(2, '0'), data[48].ToString("X").PadLeft(2, '0'));
                                            string strCmd = StringToHex(str);
                                            int num = strCmd.Split(' ').Length;
                                            string datalength = IntToHex(num).PadLeft(8, '0').ToUpper();
                                            string length1 = datalength.Substring(0, 2) + " " + datalength.Substring(2, 2) + " " + datalength.Substring(4, 2) + " " + datalength.Substring(6, 2);
                                            string crc = CRCCalc(strCmd);
                                            strCmd = "48 44 58 4D " + StringToHex(devid) + " " + StringToHex("00000000000000000000") + " 00 " + datazs + " " + length1 + " 00 00 " + crc + " " + strCmd;
                                            SendToServerMsg(strCmd);
                                        }
                                    }
                                    //删除凭证
                                    else if (message.Command.ToUpper() == "COM_DELETE_CERTIFICATE")
                                    {
                                        CardInfo card = GetVoucherInfo(message.Data[0].ToString());
                                        if (card != null)
                                        {
                                            bool result = DelVoucher(card);

                                            Message replay = new Message();
                                            replay.Command = "COM_DELETE_CERTIFICATE";
                                            if (result)
                                            {
                                                replay.Result = 0;
                                            }
                                            else
                                            {
                                                replay.Result = 1;
                                            }
                                            string str = JsonConvert.SerializeObject(replay);
                                            string datazs = string.Format("{0} {1} {2} {3}", data[45].ToString("X").PadLeft(2, '0'), data[46].ToString("X").PadLeft(2, '0'), data[47].ToString("X").PadLeft(2, '0'), data[48].ToString("X").PadLeft(2, '0'));
                                            string strCmd = StringToHex(str);
                                            int num = strCmd.Split(' ').Length;
                                            string datalength = IntToHex(num).PadLeft(8, '0');
                                            string length1 = datalength.Substring(0, 2) + " " + datalength.Substring(2, 2) + " " + datalength.Substring(4, 2) + " " + datalength.Substring(6, 2);
                                            string crc = CRCCalc(strCmd);
                                            strCmd = "48 44 58 4D " + StringToHex(devid) + " " + StringToHex("00000000000000000000") + " 00 " + datazs + " " + length1 + " 00 00 " + crc + " " + strCmd;
                                            SendToServerMsg(strCmd);

                                        }
                                    }
                                    //清除所有凭证
                                    else if (message.Command.ToUpper() == "COM_DELETE_CERTIFICATE_IN_BATCH")
                                    {
                                        CardInfo card = GetVoucherInfo(message.Data[0].ToString());
                                        if (card != null)
                                        {
                                            bool result = DelAllTypeVoucher(card.CredenceType);

                                            Message replay = new Message();
                                            replay.Command = "COM_DELETE_CERTIFICATE_IN_BATCH";
                                            if (result)
                                            {
                                                replay.Result = 0;
                                            }
                                            else
                                            {
                                                replay.Result = 1;
                                            }
                                            string str = JsonConvert.SerializeObject(replay);
                                            string datazs = string.Format("{0} {1} {2} {3}", data[45].ToString("X").PadLeft(2, '0'), data[46].ToString("X").PadLeft(2, '0'), data[47].ToString("X").PadLeft(2, '0'), data[48].ToString("X").PadLeft(2, '0'));
                                            string strCmd = StringToHex(str);
                                            int num = strCmd.Split(' ').Length;
                                            string datalength = IntToHex(num).PadLeft(8, '0');
                                            string length1 = datalength.Substring(0, 2) + " " + datalength.Substring(2, 2) + " " + datalength.Substring(4, 2) + " " + datalength.Substring(6, 2);
                                            string crc = CRCCalc(strCmd);
                                            strCmd = "48 44 58 4D " + StringToHex(devid) + " " + StringToHex("00000000000000000000") + " 00 " + datazs + " " + length1 + " 00 00 " + crc + " " + strCmd;

                                            SendToServerMsg(strCmd);
                                        }
                                    }
                                    //参数读取
                                    else if (message.Command.ToUpper() == "COM_READ_PARAMETER")
                                    {
                                        Parameter.deviceID = devid;
                                        Parameter.workMode = GetMode().ToString();
                                        ParameterReadMessage replay = new ParameterReadMessage();
                                        replay.Command = "COM_READ_PARAMETER";
                                        replay.Data = Parameter;
                                        string str = JsonConvert.SerializeObject(replay);
                                        string datazs = string.Format("{0} {1} {2} {3}", data[45].ToString("X").PadLeft(2, '0'), data[46].ToString("X").PadLeft(2, '0'), data[47].ToString("X").PadLeft(2, '0'), data[48].ToString("X").PadLeft(2, '0'));
                                        string strCmd = StringToHex(str);
                                        int num = strCmd.Split(' ').Length;
                                        string datalength = IntToHex(num).PadLeft(8, '0');
                                        string length1 = datalength.Substring(0, 2) + " " + datalength.Substring(2, 2) + " " + datalength.Substring(4, 2) + " " + datalength.Substring(6, 2);
                                        string crc = CRCCalc(strCmd);
                                        strCmd = "48 44 58 4D " + StringToHex(devid) + " " + StringToHex("00000000000000000000") + " 00 " + datazs + " " + length1 + " 00 00 " + crc + " " + strCmd;

                                        SendToServerMsg(strCmd);
                                    }
                                    //参数设置
                                    else if (message.Command.ToUpper() == "COM_SETTING_PARAMETERS")
                                    {
                                        ParameterSet parameterSet = GetParameterSet(message.Data[0].ToString());
                                        if (parameterSet != null)
                                        {
                                            devinfo = GetDevInfo();
                                            Parameter.fileServerUrl = parameterSet.fileServerUrl;
                                            Parameter.ntpServer = parameterSet.ntpServer;
                                            Parameter.httpUserName = parameterSet.httpUserName;
                                            Parameter.httpPassword = parameterSet.httpPassword;
                                            Parameter.liftCarNumber = parameterSet.liftCarNumber;
                                            Parameter.workMode = parameterSet.workMode;
                                            Parameter.lightMode = parameterSet.lightMode;
                                            Parameter.intervalTime = parameterSet.intervalTime;
                                            if (!string.IsNullOrEmpty(parameterSet.intervalTime))
                                            {
                                                try
                                                {
                                                    reporttime = Convert.ToInt32(parameterSet.intervalTime);
                                                }
                                                catch
                                                {

                                                }
                                            }
                                            else
                                            {
                                                reporttime = 0;
                                            }

                                            LogHelper.Log("恒大下发梯控模式" + parameterSet.workMode.ToString());
                                            int mode = 0;
                                            if (parameterSet.workMode == "1")
                                            {
                                                mode = 1;
                                            }
                                            UpdateLightMode(Convert.ToInt32(parameterSet.lightMode));
                                            UpdateHdStatus(mode);
                                            HDTK(mode, "恒大参数设置");
                                            if (reporttime > 0)
                                            {
                                                interval = reporttime;
                                            }
                                            else
                                            {
                                                interval = 0;
                                            }

                                            if (parameterSet.ntpServer != devinfo.ntpserver)
                                            {
                                                RaspberryPie pie = new RaspberryPie();
                                                //bool set_result = pie.SetNtp(parameterSet.ntpServer);
                                            }

                                            Message replay = new Message();
                                            replay.Command = "COM_SETTING_PARAMETERS";
                                            if (UpdateParameter(parameterSet))
                                            {
                                                replay.Result = 0;
                                            }
                                            else
                                            {
                                                replay.Result = 1;
                                            }
                                            string str = JsonConvert.SerializeObject(replay);
                                            string datazs = string.Format("{0} {1} {2} {3}", data[45].ToString("X").PadLeft(2, '0'), data[46].ToString("X").PadLeft(2, '0'), data[47].ToString("X").PadLeft(2, '0'), data[48].ToString("X").PadLeft(2, '0')); string strCmd = StringToHex(str);
                                            int num = strCmd.Split(' ').Length;
                                            string datalength = IntToHex(num).PadLeft(8, '0');
                                            string length1 = datalength.Substring(0, 2) + " " + datalength.Substring(2, 2) + " " + datalength.Substring(4, 2) + " " + datalength.Substring(6, 2);
                                            string crc = CRCCalc(strCmd);
                                            strCmd = "48 44 58 4D " + StringToHex(devid) + " " + StringToHex("00000000000000000000") + " 00 " + datazs + " " + length1 + " 00 00 " + crc + " " + strCmd;

                                            SendToServerMsg(strCmd);
                                        }
                                    }
                                    //批量查询轿厢状态
                                    else if (message.Command.ToUpper() == "FAC_LIFT_BA_STATUS")
                                    {

                                        StatusQuery statusQuery = GetCarStatusQuery(message.Data[0].ToString());
                                        if (statusQuery.carIDList.Contains(devinfo.liftid.ToString().PadLeft(2, '0')))
                                        {
                                            // QueryAllCarStatus();
                                        }
                                    }
                                    //目录查询
                                    else if (message.Command.ToUpper() == "COM_QUERY_DIR")
                                    {
                                        CatalogueData msgdata = new CatalogueData();
                                        msgdata.Command = "COM_QUERY_DIR";
                                        CatalogueInfo catalogue = new CatalogueInfo();
                                        catalogue.deviceID = subdevid;
                                        catalogue.name = "OTIS" + devinfo.liftid.ToString();
                                        catalogue.subDeviceType = 3036;
                                        catalogue.version = getversion();
                                        List<CatalogueInfo> list = new List<CatalogueInfo>();
                                        list.Add(catalogue);
                                        msgdata.Data = list;
                                        string datazs = string.Format("{0} {1} {2} {3}", data[45].ToString("X").PadLeft(2, '0'), data[46].ToString("X").PadLeft(2, '0'), data[47].ToString("X").PadLeft(2, '0'), data[48].ToString("X").PadLeft(2, '0'));
                                        string str = JsonConvert.SerializeObject(msgdata);
                                        string strCmd = StringToHex(str);
                                        int num = strCmd.Split(' ').Length;
                                        string datalength = IntToHex(num).PadLeft(8, '0');
                                        string length1 = datalength.Substring(0, 2) + " " + datalength.Substring(2, 2) + " " + datalength.Substring(4, 2) + " " + datalength.Substring(6, 2);
                                        string crc = CRCCalc(strCmd);
                                        strCmd = "48 44 58 4D " + StringToHex(devid) + " " + StringToHex("00000000000000000000") + " 00 " + datazs + " " + length1 + " 00 00 " + crc + " " + strCmd;

                                        SendToServerMsg(strCmd);
                                    }
                                    //人脸识别
                                    else if (message.Command.ToUpper() == "ISSUE_COMMAND")
                                    {
                                        CmdMessage cmd = GetCmdInfo(message.Data[0].ToString());
                                        if (cmd != null)
                                        {
                                            SendCmdToTK(cmd.Cmd, cmd.DevNo, cmd.Address, cmd.DataLen);
                                        }
                                    }
                                    else if (message.Command.ToUpper() == "COM_DEV_REGISTER")
                                    {
                                        List<byte> data_result = data.GetRange(57, data.Count - 57);
                                        string result = Encoding.GetEncoding("utf-8").GetString(data_result.ToArray(), 0, data_result.Count);
                                        RegisterReturnInfo info = JsonConvert.DeserializeObject<RegisterReturnInfo>(result);
                                        if (info.Result == 0)
                                        {
                                            hdpt_reg_flag = true;
                                            hdpt_heart_flag = true;
                                            hdstatus = 2;
                                            hdpt_heart_time = DateTime.Now;
                                        }
                                    }
                                    else if (message.Command.ToUpper() == "COM_HEARTBEAT")
                                    {
                                        List<byte> data_result = data.GetRange(57, data.Count - 57);
                                        string result = Encoding.GetEncoding("utf-8").GetString(data_result.ToArray(), 0, data_result.Count);
                                        RegisterReturnInfo info = JsonConvert.DeserializeObject<RegisterReturnInfo>(result);
                                        if (info.Result == 0)
                                        {
                                            hdpt_heart_time = DateTime.Now;
                                        }
                                    }

                                }
                            }
                            catch (Exception e)
                            {
                                continue;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    continue;
                }
            }
        }

        public bool SendCmdToTK(string cmd, int devid, int add, int count)
        {
            try
            {
                cmdlist.Add(cmd);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool HDTK(int value, string type)
        {
            if (value == 1)
            {
                if (HDLadderControl(liftid))//授权
                {
                    ModeRecord modeRecord = new ModeRecord();
                    modeRecord.workmode = value;
                    modeRecord.reason = type;
                    modeRecord.updatetime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    InsertModeRecord(modeRecord);
                    return true;
                }
            }
            else
            {
                if (HDExitControl(liftid))//退出梯控
                {
                    ModeRecord modeRecord = new ModeRecord();
                    modeRecord.workmode = value;
                    modeRecord.reason = type;
                    modeRecord.updatetime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    InsertModeRecord(modeRecord);
                    return true;
                }
            }
            return false;
        }

        //更新梯控模式
        public bool UpdateLightMode(int value)
        {
            try
            {
                if (UpdateLight(value))
                {
                    light = value;
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }

        public bool UpdateLight(int mode)
        {
            string strSql = "UPDATE devinfo SET lightmode=" + mode;
            CommFN<DevInfo> fn = new CommFN<DevInfo>();
            return fn.ExecFN(strSql);
        }

        //更新数据库参数
        public bool UpdateParameter(ParameterSet para)
        {
            string strSql = string.Format(@"UPDATE devinfo SET intervalTime={0},ntpserver='{1}'", Convert.ToInt32(para.intervalTime), para.ntpServer);
            CommFN<CardInfo> fn = new CommFN<CardInfo>();
            return fn.ExecFN(strSql);
        }
        //读取电梯梯控状态
        public int GetMode()
        {
            if (ele_control == 1)
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }

        //设备注册
        public bool HDDevReister(DevInfo devinfo)
        {
            try
            {
                int packnum = count;
                if (!string.IsNullOrEmpty(devinfo.serverIP) && devinfo.serverport > 0)
                {
                    HDRegInfo data1 = new HDRegInfo();
                    data1.mac = GetLocalMac();
                    data1.manufacturer = "1011";
                    data1.ip = devinfo.localIP;
                    data1.mask = devinfo.mask;
                    data1.deviceID = "1011" + "2020" + data1.mac.Replace("-", "");
                    DataSaveLogHelper.Log("注册信息" + JsonConvert.SerializeObject(data1));
                    devid = data1.deviceID;
                    HDMessageData msgdata = new HDMessageData();
                    msgdata.Command = "COM_DEV_REGISTER";
                    List<HDRegInfo> list = new List<HDRegInfo>();
                    list.Add(data1);
                    msgdata.Data = list;
                    string str = JsonConvert.SerializeObject(msgdata);
                    string zs = IntToHex(packnum).PadLeft(8, '0');
                    string datazs = zs.Substring(0, 2) + " " + zs.Substring(2, 2) + " " + zs.Substring(4, 2) + " " + zs.Substring(6, 2);
                    string strCmd = StringToHex(str);
                    int num = strCmd.Split(' ').Length;
                    string datalength = IntToHex(num).PadLeft(8, '0');
                    string length = datalength.Substring(0, 2) + " " + datalength.Substring(2, 2) + " " + datalength.Substring(4, 2) + " " + datalength.Substring(6, 2);
                    string crc = CRCCalc(strCmd);
                    strCmd = "48 44 58 4D " + StringToHex(data1.deviceID) + " " + StringToHex("00000000000000000000") + " 00 " + datazs + " " + length + " 00 00 " + crc + " " + strCmd;
                    return SendToServerMsg(strCmd);
                }
                return false;
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
                return false;
            }
        }

        //发送消息
        public bool SendToServerMsg(string str)
        {
            lock (sendlocker)
            {
                try
                {
                    if (server.Connected == true)
                    {
                        try
                        {
                            string senddata = string.Format(@"{0}", str);
                            server.Send(HexStringToByteArray(senddata));
                            DataSaveLogHelper.Log("发送成功" + str);
                        }
                        catch (Exception ex)
                        {
                            DataSaveLogHelper.Log("发送异常" + str + ex.ToString());
                            //isReg = false;
                            return false;
                        }

                        if (count < 2147483647)
                        {
                            count++;
                        }
                        else
                        {
                            count = 1;
                        }
                        return true;
                    }
                    else
                    {
                        hdpt_connect_flag = false;
                        hdpt_heart_flag = false;
                        hdpt_reg_flag = false;
                    }
                    return true;
                }
                catch (Exception ex)
                {
                    DataSaveLogHelper.Log("发送异常" + str + ex.ToString());
                    hdpt_connect_flag = false;
                    hdpt_heart_flag = false;
                    hdpt_reg_flag = false;
                    return false;
                }
            }
        }

        //发送心跳
        public bool HDHeartSend()
        {
            try
            {
                SendData msgdata = new SendData();
                msgdata.Data = null;
                msgdata.Command = "COM_HEARTBEAT";
                int packnum = count;
                string zs = IntToHex(packnum).PadLeft(8, '0'); ;
                string datazs = zs.Substring(0, 2) + " " + zs.Substring(2, 2) + " " + zs.Substring(4, 2) + " " + zs.Substring(6, 2);
                string str = JsonConvert.SerializeObject(msgdata);
                string strCmd = StringToHex(str);
                int num = strCmd.Split(' ').Length;
                string datalength = IntToHex(num).PadLeft(8, '0');
                string length = datalength.Substring(0, 2) + " " + datalength.Substring(2, 2) + " " + datalength.Substring(4, 2) + " " + datalength.Substring(6, 2);
                string crc = CRCCalc(strCmd);
                strCmd = "48 44 58 4D " + StringToHex(devid) + " " + StringToHex("00000000000000000000") + " 00 " + datazs + " " + length + " 00 00 " + crc + " " + strCmd;

                return SendToServerMsg(strCmd);
            }
            catch (Exception e)
            {
                return false;
            }
        }

        //定时连接恒大平台
        public void HDConnect()
        {
            devinfo.mac = GetLocalMac();
            devinfo.localIP = GetLocalIP();
            subdevid = "3063" + devinfo.mac.Replace("-", "") + devinfo.liftid.ToString("X").PadLeft(4, '0');

            Task task = new Task(async () =>
            {
                while (true)
                {
                    if (!hdpt_connect_flag)
                    {
                        bool result = ConnectServer(devinfo.serverIP, devinfo.serverport);
                        if (result)
                        {
                            hdstatus = 1;
                            hdpt_connect_flag = true;
                            HDDevReister(devinfo);
                        }
                    }
                    else
                    {
                        if (!hdpt_reg_flag)
                        {
                            HDDevReister(devinfo);
                        }
                    }
                    await Task.Delay(60000);

                }
            });
            task.Start();
        }

        //定时发送心跳
        public void HDHeart()
        {
            Task task = new Task(async () =>
            {
                while (true)
                {
                    if (hdpt_connect_flag && hdpt_reg_flag && hdpt_heart_flag)
                    {
                        TimeSpan secondSpan = new TimeSpan(DateTime.Now.Ticks - hdpt_heart_time.Ticks);
                        if (secondSpan.TotalSeconds > 180)
                        {
                            hdpt_heart_flag = false;
                            hdpt_reg_flag = false;
                        }
                        else
                        {
                            HDHeartSend();
                        }
                    }
                    await Task.Delay(60000);

                }
            });
            task.Start();
        }

        //获取本机IP
        public string GetLocalIP()
        {
            string localIP = string.Empty;
            try
            {
                using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
                {
                    socket.Connect("8.8.8.8", 65530);
                    IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
                    localIP = endPoint.Address.ToString();
                }
                return localIP;
            }
            catch
            {
                return "";
            }
        }
        //获取本机mac地址
        public string GetLocalMac()
        {
            string macAddress = "";
            try
            {
                foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
                {
                    if (nic.OperationalStatus == OperationalStatus.Up)
                    {
                        macAddress = nic.GetPhysicalAddress().ToString();
                        IPInterfaceProperties ipProperties = nic.GetIPProperties();
                        UnicastIPAddressInformation curIP = ipProperties.UnicastAddresses[0];
                        string ip = curIP.Address.ToString();
                        string mask = curIP.IPv4Mask.ToString();
                        string server = ipProperties.GatewayAddresses[0].Address.ToString();
                        break;
                    }
                }
                return macAddress;
            }
            catch
            {
                return "";
            }
        }
        /// <summary>
        /// 批量查询
        /// </summary>
        public bool QueryAllCarStatus()
        {
            CarStatus carStatus = new CarStatus();
            ElevatorPoint point = new ElevatorPoint();
            int index = status_list.FindIndex(x => x.liftid == liftid);
            if (index > -1)
            {
                // point = status_list[index];
            }
            //memoryCache = GetStatusMemory();
            // memoryCache.TryGetValue(devinfo.liftid, out point);
            ElevatorStatus status = new ElevatorStatus();
            if (point != null)
            {
                status.deviceID = subdevid;
                status.carID = devinfo.liftid.ToString().PadLeft(2, '0');
                status.physicalfloor = point.physicalfloor;
                status.displayfloor = point.Showfloor;
                if (point.up == 1)
                {
                    status.status = "01";
                }
                else if (point.down == 1)
                {
                    status.status = "02";
                }
                else
                {
                    status.status = "00";
                }

                if (point.frontdooropening == 1)
                {
                    status.doorStatus = "10";
                }
                else if (point.frontdooropened == 1)
                {
                    status.doorStatus = " 11";
                }
                else if (point.frontdoorcloseing == 1)
                {
                    status.doorStatus = " 12";
                }
                else if (point.frontdoorclosed == 1)
                {
                    status.doorStatus = " 13";
                }

                if (point.falut == 1)
                {
                    status.errorStatus = 1;
                }
                else
                {
                    status.errorStatus = 0;
                }
            }

            carStatus.Command = "FAC_LIFT_BA_STATUS";
            carStatus.Data.statusList.Add(status);
            string str = JsonConvert.SerializeObject(carStatus);
            string zs = IntToHex(count).PadLeft(8, '0'); ;
            string datazs = zs.Substring(0, 2) + " " + zs.Substring(2, 2) + " " + zs.Substring(4, 2) + " " + zs.Substring(6, 2);
            string strCmd = StringToHex(str);
            int num = strCmd.Split(' ').Length;
            string datalength = IntToHex(num).PadLeft(8, '0');
            string length = datalength.Substring(0, 2) + " " + datalength.Substring(2, 2) + " " + datalength.Substring(4, 2) + " " + datalength.Substring(6, 2);
            string crc = CRCCalc(strCmd);
            strCmd = "48 44 58 4D " + StringToHex(devid) + " " + StringToHex("00000000000000000000") + " 00 " + datazs + " " + length + " 00 00 " + crc + " " + strCmd;
            if (SendToServerMsg(strCmd))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 凭证解析
        /// </summary>
        public CardInfo GetVoucherInfo(string data)
        {
            CardInfo cardInfo;
            try
            {
                cardInfo = JsonConvert.DeserializeObject<CardInfo>(data);
            }
            catch
            {
                LogHelper.Log("凭证为空");
                return null;
            }
            return cardInfo;
        }

        /// <summary>
        /// 解析类型
        /// </summary>
        public ReceiveData AnalysisType(List<byte> data1)
        {
            ReceiveData message;
            try
            {
                List<byte> data = data1.GetRange(57, data1.Count - 57);
                string result = string.Empty;
                result = Encoding.GetEncoding("utf-8").GetString(data.ToArray(), 0, data.Count);
                message = JsonConvert.DeserializeObject<ReceiveData>(result);
            }
            catch
            {
                return null;
            }
            return message;
        }

        /// <summary>
        /// 参数设置解析
        /// </summary>
        public ParameterSet GetParameterSet(string data)
        {
            ParameterSet para;
            try
            {
                para = JsonConvert.DeserializeObject<ParameterSet>(data);
            }
            catch
            {
                return null;
            }
            return para;
        }

        /// <summary>
        /// 状态查询解析
        /// </summary>
        public StatusQuery GetCarStatusQuery(string data)
        {
            StatusQuery status;
            try
            {
                status = JsonConvert.DeserializeObject<StatusQuery>(data);
            }
            catch
            {
                return null;
            }
            return status;
        }

        /// <summary>
        /// 命令解析
        /// </summary>
        public CmdMessage GetCmdInfo(string data)
        {
            CmdMessage message;
            try
            {
                message = JsonConvert.DeserializeObject<CmdMessage>(data);
            }
            catch
            {
                return null;
            }
            return message;
        }

        /// <summary>
        /// 解析回复数据
        /// </summary>
        public InitReplayData AnalysisReplay(List<byte> data1)
        {
            InitReplayData message;
            try
            {
                List<byte> data = data1.GetRange(57, data1.Count - 57);
                string result = string.Empty;
                result = Encoding.GetEncoding("utf-8").GetString(data.ToArray(), 0, data.Count);
                message = JsonConvert.DeserializeObject<InitReplayData>(result);
            }
            catch
            {
                return null;
            }
            return message;
        }

        public static byte[] HexStringToByteArray(string s)
        {
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            return buffer;
        }

        //新增凭证
        public bool InsertVoucher(CardInfo cardInfo)
        {
            string strSql = string.Format(@"INSERT INTO cardinfo(cardID,StartTime,OverTime,subDeviceID,UserType,CredenceType,username,UUID,elevatorAuthFloor)VALUES('{0}','{1}','{2}','{3}',{4},{5},'{6}','{7}','{8}')", cardInfo.credenceNo, cardInfo.startTime, cardInfo.endTime, cardInfo.subDeviceID, 3, cardInfo.CredenceType, "", cardInfo.userID, string.Join(",", cardInfo.elevatorAuthFloor));
            CommFN<CardInfo> fn = new CommFN<CardInfo>();
            return fn.ExecFN(strSql);
        }

        //根据uuid查询凭证
        public VoucherInfo QueryVoucher(CardInfo cardInfo)
        {
            string strSql = string.Format(@"SELECT * FROM cardinfo WHERE UUID='{0}'", cardInfo.userID);
            CommFN<VoucherInfo> fn = new CommFN<VoucherInfo>();
            return fn.GetData(strSql);
        }

        //更新凭证
        public bool UpdateVoucher(CardInfo cardInfo)
        {
            string strSql = string.Format(@"UPDATE cardinfo SET cardID='{0}',StartTime='{1}',OverTime='{2}',subDeviceID='{3}',UserType='{4}',CredenceType={5},username='{6}',elevatorAuthFloor='{7}' WHERE UUID='{8}'", cardInfo.credenceNo, cardInfo.startTime, cardInfo.endTime, cardInfo.subDeviceID, 3, cardInfo.CredenceType, "", string.Join(",", cardInfo.elevatorAuthFloor), cardInfo.userID);
            CommFN<VoucherInfo> fn = new CommFN<VoucherInfo>();
            return fn.ExecFN(strSql);
        }

        //删除凭证
        public bool DelVoucher(CardInfo cardInfo)
        {
            string strSql = string.Format(@"DELETE FROM cardinfo WHERE UUID='{0}'", cardInfo.userID);
            CommFN<VoucherInfo> fn = new CommFN<VoucherInfo>();
            return fn.ExecFN(strSql);
        }

        //清除所有凭证
        public bool DelAllTypeVoucher(int type)
        {
            string strSql = "DELETE FROM cardinfo";
            CommFN<VoucherInfo> fn = new CommFN<VoucherInfo>();
            return fn.ExecFN(strSql);
        }

        //更新平台下发梯控状态
        public bool UpdateHdStatus(int value)
        {
            try
            {
                if (UpdateModeStatus(value))
                {
                    if (value == 1)
                    {
                        TcpAuthorize = true;
                    }
                    else if (value == 0)
                    {
                        TcpAuthorize = false;
                    }
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }

        //更新后台数据库 梯控状态
        public bool UpdateModeStatus(int mode)
        {
            string strSql = "UPDATE devinfo SET workmode=" + mode + ",updatetime='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "'";
            CommFN<DevInfo> fn = new CommFN<DevInfo>();
            return fn.ExecFN(strSql);
        }
        public int hd()
        {
            return hdstatus;
        }
        #endregion

        public void CarStatusServer()
        {
            try
            {
                Task task = new Task(async () =>
                {
                    if (report_token.IsCancellationRequested)
                    {
                        return;
                    }
                    report_resetEvent.WaitOne();
                    //do something

                }, report_token);
                task.Start();
            }
            catch (Exception e)
            {
                LogHelper.Log(e.ToString());
            }
            /* try
             {
                 reporttimer = new System.Timers.Timer(Convert.ToDouble(reporttime));

                 reporttimer.Elapsed += new ElapsedEventHandler(CarStatusReport);//到达时间的时候执行事件；

                 reporttimer.AutoReset = true;//设置是执行一次（false）还是一直执行(true)；

                 reporttimer.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件；
                 isreport = true;
             }
             catch (Exception ex)
             {
                 logPrint.Log("报错信息：" + ex.ToString());
             }*/
        }

        #region 连接主梯
        public Socket master_server;
        public Thread master_thread;
        public static bool master_connect_flag = false;//主梯连接
        public DateTime slave_msg_time = DateTime.Now;//副梯收到主梯最新时间
        public void MsterConnect()
        {
            Task task = new Task(async () =>
            {
                while (true)
                {
                    if (!master_connect_flag)
                    {
                        bool result = ConnectMaster(devinfo.mainIP, devinfo.mainPort);
                        if (result)
                        {
                            master_connect_flag = true;
                        }
                    }
                    else
                    {
                        if (!master_server.Connected)
                        {
                            master_connect_flag = false;
                        }
                    }
                    await Task.Delay(60000);

                }
            });
            task.Start();
        }

        public bool ConnectMaster(string serverIP, int port)
        {
            try
            {
                master_server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                master_server.Connect(serverIP, port);
                //server.ReceiveTimeout = 10000;
                master_thread = new Thread(StartMasterReceive);
                master_thread.Start(master_server);
                return true;
            }
            catch (Exception e)
            {
                LogHelper.Log("连接主梯异常" + e.ToString());
                // logPrint.Log("连接恒大异常");
                return false;
            }
        }

        public void StartMasterReceive(object obj)
        {
            byte[] buffer = new byte[2048];
            int length = 0;
            while (true)
            {
                try
                {
                    length = master_server.Receive(buffer);
                    if (length == 0)
                    {
                        break;
                    }
                    else
                    {
                        slave_msg_time = DateTime.Now;
                    }
                }
                catch (Exception ex)
                {
                    continue;
                }
            }
        }

        public void SendToServer(string msg)
        {
            try
            {
                if (master_server != null && master_server.Connected)
                {
                    master_server.Send(Encoding.UTF8.GetBytes(msg));
                    master_server.ReceiveTimeout = 4000;
                    byte[] data = new byte[1024];
                    int count = master_server.Receive(data);
                    if (count > 0)
                    {
                        statussend = DateTime.Now;
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Log(ex.ToString());
            }
        }

        #endregion

        #region 副梯监测主梯连接情况
        public static bool SlaveConnect = false;//副梯监测是否连接主梯

        public void CheckMasterConnectStatus()
        {
            Task task = new Task(async () =>
            {
                while (true)
                {
                    try
                    {
                        int sj = MasterConnectTime();
                        if (sj > 2000 && SlaveConnect)
                        {
                            SlaveConnect = false;
                        }
                        else if (sj <= 2000 && !SlaveConnect)
                        {
                            SlaveConnect = true;
                        }
                    }
                    catch
                    {

                    }
                    await Task.Delay(200);

                }
            });
            task.Start();
        }

        public int MasterConnectTime()
        {
            int i = 999999;
            if (slave_msg_time.Year == 1)
            {
                return i;
            }
            else
            {
                TimeSpan ts1 = new TimeSpan(DateTime.Now.Ticks);
                TimeSpan ts2 = new TimeSpan(slave_msg_time.Ticks);
                TimeSpan ts3 = ts1.Subtract(ts2).Duration();
                i = (int)ts3.TotalMilliseconds;
            }

            return i;
        }


        #endregion

        #region 主梯建立服务端
        public DateTime slavsendtime;//主梯接收到副梯状态最新时间
        Dictionary<string, Socket> dict = new Dictionary<string, Socket>(); //套接字集合

        public byte[] dataBuffer = new byte[1024];
        public Socket serverSocket = null;
        public void StartServer(/*string ip,*/ int port)
        {
            try
            {
                // 地址类型;socket类型:Dgram(UDP报文) TCP流Stream;协议
                serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                // 申请端口
                //IPAddress ipAddress = IPAddress.Parse(ip); // Parse把一个ip字符串转换成对象传递
                IPAddress ipAddress = IPAddress.Any;

                // IpAdress xx.xx.xx.xx IpEedPoint IP地址+终端号
                IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, port);

                // 绑定ip和端口号
                serverSocket.Bind(ipEndPoint);

                // 开始监听端口 设置50防止服务器崩溃 设置0表示不限制数量
                serverSocket.Listen(50); // 传递挂起的连接队列的最大长度 

                // 接收客户端信息 程序会暂停，直到有一个客户端连接过来才会继续向下运行
                // Socket clientSocket = serverSocket.Accept(); // 接收一个客户端连接 返回一个Socket用来跟客户端进行通信
                serverSocket.BeginAccept(AcceptCallBack, serverSocket);
            }
            catch
            {
                LogHelper.Log("建立服务端失败");
            }
        }

        // 回调函数 接收到一个客户端连接的时候，要对客户端发起监听
        public void AcceptCallBack(IAsyncResult ar)
        {
            try
            {
                Socket serverSocket = ar.AsyncState as Socket;
                Socket clientSocket = serverSocket.EndAccept(ar);
                // 向客户端发送一条数据
                string msg = "01";
                byte[] data = Encoding.UTF8.GetBytes(msg); // 按照utf8将一个字符串转换成byte数组
                clientSocket.Send(data); // Send传递byte数组，需要将字符串转换成byte数组 需要使用支持中文的编码

                dict.Add(clientSocket.RemoteEndPoint.ToString(), clientSocket);

                // 持续不断的接收消息 BeginReceive()开始异步接收数据  偏移从0开始存，1024最大数量，事件方法，
                clientSocket.BeginReceive(dataBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, clientSocket);

                // 接收完一个客户端之后，重新调用 继续处理下一个客户端连接
                serverSocket.BeginAccept(AcceptCallBack, serverSocket);
            }
            catch
            {

            }
        }

        // 当服务器端接收到一条消息的时候，就会调用事件方法 如果想再去处理，传递数据的时候可以通过null进行传递
        public void ReceiveCallBack(IAsyncResult ar)
        {
            // 使用try catch处理客户端异常关闭终端
            // 调用完BeginReceive，表示开始监听客户端数据的传递，当它就收到一条客户端数据的时候才会去调用
            // 把clientSocket当成一个参数传递到回调方法里面，通过ar.AsyncState来获取到Socket
            Socket clientSocket = null;
            try
            {
                clientSocket = ar.AsyncState as Socket;
                clientSocket.ReceiveTimeout = 10000;
                int count = clientSocket.EndReceive(ar); // 完成数据的接收  count代表接收了多少个字节的数据
                // 如果没有接收到数据就关闭 
                if (count == 0)
                {
                    dict.Remove(clientSocket.RemoteEndPoint.ToString());
                    clientSocket.Close();
                    return;
                }
                // utf-8进行反编码
                string msg = Encoding.UTF8.GetString(dataBuffer, 0, count);
                slavsendtime = DateTime.Now;
                GroupSendClient("01");
                //LogHelper.Log(slavsendtime.ToString());

                // 完成回调 一直接收数据
                clientSocket.BeginReceive(dataBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, clientSocket);
            }
            catch (Exception e)
            {
                // 只出异常时关闭连接
                if (clientSocket != null)
                {
                    if (dict.Count > 0)
                    {
                        dict.Remove(clientSocket.RemoteEndPoint.ToString());
                        clientSocket.Close();
                    }
                }
            }
        }
        public void GroupSendClient(string msg)
        {
            byte[] buffer = HexStringToByteArray(msg);
            foreach (Socket socket in dict.Values)
            {
                try
                {
                    socket.Send(buffer);
                }
                catch
                {
                    continue;
                }
            }
        }
        #endregion

        #region 主梯监测副梯连接情况
        public bool MasterConnect = false;//主梯监测副梯连接状态

        public void CheckSlaveConnectStatus()
        {
            Task task = new Task(async () =>
            {
                while (true)
                {
                    try
                    {
                        int sj = SlaveConnectTime();
                        if (sj > 2000 && MasterConnect)
                        {
                            MasterConnect = false;
                        }
                        else if (sj <= 2000 && !MasterConnect)
                        {
                            MasterConnect = true;
                        }
                    }
                    catch
                    {

                    }
                    await Task.Delay(200);

                }
            });
            task.Start();
        }

        public int SlaveConnectTime()
        {
            int i = 999999;
            if (slavsendtime.Year == 1)
            {
                return i;
            }
            else
            {
                TimeSpan ts1 = new TimeSpan(DateTime.Now.Ticks);
                TimeSpan ts2 = new TimeSpan(slavsendtime.Ticks);
                TimeSpan ts3 = ts1.Subtract(ts2).Duration();
                i = (int)ts3.TotalMilliseconds;
            }

            return i;
        }
        #endregion

        #region 电梯轿厢状态上报
        public void ElevatorStatusReport()
        {
            Task task = new Task(async () =>
            {
                while (true)
                {
                    try
                    {
                        if (interval > 0)
                        {
                            Report(liftid);
                            await Task.Delay(interval);
                        }
                        else
                        {
                            await Task.Delay(1000);
                        }
                    }
                    catch
                    {
                        await Task.Delay(1000);
                    }
                }
            });
            task.Start();
        }

        public void Report(int devid)
        {
            try
            {
                HDZHCurrentElevatorStatus point = new HDZHCurrentElevatorStatus();
                int index = status_list.FindIndex(x => x.liftid == devid);
                if (index > -1)
                {
                    point = status_list[index];
                    Device elevator = new Device();
                    if (point.Fault == 1)
                    {
                        elevator.State = 2;
                    }
                    else
                    {
                        elevator.State = 1;
                    }

                    elevator.Floor = point.PhysicalFloor;

                    if (point.Up == 1)
                    {
                        elevator.Dicrection = 1;
                    }
                    else if (point.Down == 1)
                    {
                        elevator.Dicrection = 2;
                    }
                    else
                    {
                        elevator.Dicrection = 0;
                    }

                    ElevatorDevReport(elevator);
                }
            }
            catch
            {

            }
        }

        /// <summary>
        /// 电梯设备状态上报
        /// </summary>
        public void ElevatorDevReport(Device dev)
        {
            if (!string.IsNullOrEmpty(subdevid))
            {
                dev.deviceID = subdevid;
                List<Device> list = new List<Device>();
                list.Add(dev);
                ElevatorEquipment elevator = new ElevatorEquipment();
                elevator.Command = "FAC_UPLOAD_DEV_STATUS";
                elevator.Data = list;
                string str = JsonConvert.SerializeObject(elevator);
                string zs = IntToHex(count).PadLeft(8, '0'); ;
                string datazs = zs.Substring(0, 2) + " " + zs.Substring(2, 2) + " " + zs.Substring(4, 2) + " " + zs.Substring(6, 2);
                string strCmd = StringToHex(str);
                int num = strCmd.Split(' ').Length;
                string datalength = IntToHex(num).PadLeft(8, '0');
                string length = datalength.Substring(0, 2) + " " + datalength.Substring(2, 2) + " " + datalength.Substring(4, 2) + " " + datalength.Substring(6, 2);
                string crc = CRCCalc(strCmd);
                strCmd = "48 44 58 4D " + StringToHex(devid) + " " + StringToHex("00000000000000000000") + " 00 " + datazs + " " + length + " 00 00 " + crc + " " + strCmd;
                SendToServerMsg(strCmd);
            }
        }
        #endregion
    }
}
